PageRenderTime 99ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/subprojects/platform-native/src/integTest/groovy/org/gradle/nativeplatform/LibraryDependenciesIntegrationTest.groovy

https://github.com/andrewhj-mn/gradle
Groovy | 399 lines | 338 code | 45 blank | 16 comment | 9 complexity | 9b99dd0108007c4657cc84e627e83c6d MD5 | raw file
  1. /*
  2. * Copyright 2012 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.gradle.nativeplatform
  17. import org.gradle.nativeplatform.fixtures.AbstractInstalledToolChainIntegrationSpec
  18. import org.gradle.nativeplatform.fixtures.app.CppHelloWorldApp
  19. import org.gradle.nativeplatform.fixtures.app.ExeWithDiamondDependencyHelloWorldApp
  20. import org.gradle.nativeplatform.fixtures.app.ExeWithLibraryUsingLibraryHelloWorldApp
  21. import org.gradle.util.Requires
  22. import org.gradle.util.TestPrecondition
  23. import spock.lang.Unroll
  24. @Requires(TestPrecondition.CAN_INSTALL_EXECUTABLE)
  25. class LibraryDependenciesIntegrationTest extends AbstractInstalledToolChainIntegrationSpec {
  26. def "setup"() {
  27. settingsFile << "rootProject.name = 'test'"
  28. buildFile << """
  29. allprojects {
  30. apply plugin: "cpp"
  31. // Allow static libraries to be linked into shared
  32. binaries.withType(StaticLibraryBinarySpec) {
  33. if (toolChain in Gcc || toolChain in Clang) {
  34. cppCompiler.args '-fPIC'
  35. }
  36. }
  37. }
  38. """
  39. }
  40. @Unroll
  41. def "produces reasonable error message when referenced library #label"() {
  42. given:
  43. def app = new CppHelloWorldApp()
  44. app.executable.writeSources(file("exe/src/main"))
  45. app.library.writeSources(file("lib/src/hello"))
  46. and:
  47. settingsFile.text = "include ':exe', ':other'"
  48. buildFile << """
  49. project(":exe") {
  50. model {
  51. components {
  52. main(NativeExecutableSpec) {
  53. sources {
  54. cpp.lib ${dependencyNotation}
  55. }
  56. }
  57. hello(NativeLibrarySpec)
  58. }
  59. }
  60. }
  61. project(":other") {
  62. model {
  63. components {
  64. hello(NativeLibrarySpec)
  65. }
  66. }
  67. }
  68. """
  69. when:
  70. fails ":exe:mainExecutable"
  71. then:
  72. failure.assertHasDescription(description)
  73. failure.assertHasCause(cause)
  74. where:
  75. label | dependencyNotation | description | cause
  76. "does not exist" | "library: 'unknown'" | "Could not locate library 'unknown'." | "NativeLibrarySpec with name 'unknown' not found."
  77. "project that does not exist" | "project: ':unknown', library: 'hello'" | "Could not locate library 'hello' for project ':unknown'." | "Project with path ':unknown' could not be found in project ':exe'."
  78. "does not exist in referenced project" | "project: ':other', library: 'unknown'" | "Could not locate library 'unknown' for project ':other'." | "NativeLibrarySpec with name 'unknown' not found."
  79. }
  80. @Unroll
  81. def "can use #notationName notation to reference library in same project"() {
  82. given:
  83. def app = new CppHelloWorldApp()
  84. app.executable.writeSources(file("src/main"))
  85. app.library.writeSources(file("src/hello"))
  86. and:
  87. buildFile << """
  88. model {
  89. components { comp ->
  90. hello(NativeLibrarySpec)
  91. main(NativeExecutableSpec) {
  92. sources {
  93. cpp.lib ${notation}
  94. }
  95. }
  96. }
  97. }
  98. """
  99. when:
  100. succeeds "installMainExecutable"
  101. then:
  102. installation("build/install/mainExecutable").exec().out == app.englishOutput
  103. where:
  104. notationName | notation
  105. "direct" | "comp.hello"
  106. "map" | "library: 'hello'"
  107. }
  108. @Unroll
  109. def "can use map #notationName notation to reference library dependency of binary"() {
  110. given:
  111. def app = new CppHelloWorldApp()
  112. app.executable.writeSources(file("src/main"))
  113. app.library.writeSources(file("src/hello"))
  114. and:
  115. buildFile << """
  116. model {
  117. components { comp ->
  118. hello(NativeLibrarySpec)
  119. main(NativeExecutableSpec) {
  120. binaries.all { binary ->
  121. binary.lib ${notation}
  122. }
  123. }
  124. }
  125. }
  126. """
  127. when:
  128. succeeds "installMainExecutable"
  129. then:
  130. installation("build/install/mainExecutable").exec().out == app.englishOutput
  131. where:
  132. notationName | notation
  133. "direct" | "comp.hello"
  134. "map" | "library: 'hello'"
  135. }
  136. def "can use map notation to reference static library in same project"() {
  137. given:
  138. def app = new CppHelloWorldApp()
  139. app.executable.writeSources(file("src/main"))
  140. app.library.writeSources(file("src/hello"))
  141. and:
  142. buildFile << """
  143. model {
  144. components {
  145. main(NativeExecutableSpec) {
  146. sources {
  147. cpp.lib library: 'hello', linkage: 'static'
  148. }
  149. }
  150. hello(NativeLibrarySpec)
  151. }
  152. }
  153. """
  154. when:
  155. succeeds "mainExecutable"
  156. then:
  157. executable("build/binaries/mainExecutable/main").exec().out == app.englishOutput
  158. }
  159. @Unroll
  160. def "can use map notation to reference library in different project#label"() {
  161. given:
  162. def app = new CppHelloWorldApp()
  163. app.executable.writeSources(file("exe/src/main"))
  164. app.library.writeSources(file("lib/src/hello"))
  165. and:
  166. settingsFile.text = "include ':lib', ':exe'"
  167. buildFile << """
  168. project(":exe") {
  169. ${explicitEvaluation}
  170. model {
  171. components {
  172. main(NativeExecutableSpec) {
  173. sources {
  174. cpp.lib project: ':lib', library: 'hello'
  175. }
  176. }
  177. }
  178. }
  179. }
  180. project(":lib") {
  181. model {
  182. components {
  183. hello(NativeLibrarySpec)
  184. }
  185. }
  186. }
  187. """
  188. when:
  189. if (configureOnDemand) {
  190. executer.withArgument('--configure-on-demand')
  191. }
  192. succeeds ":exe:installMainExecutable"
  193. then:
  194. installation("exe/build/install/mainExecutable").exec().out == app.englishOutput
  195. where:
  196. label | configureOnDemand | explicitEvaluation
  197. "" | false | ""
  198. " with configure-on-demand" | true | ""
  199. // " with evaluationDependsOn" | false | "evaluationDependsOn(':lib')"
  200. " with afterEvaluate" | false | """
  201. project.afterEvaluate {
  202. binaries*.libs*.linkFiles.files.each { println it }
  203. }
  204. """
  205. }
  206. def "can use map notation to transitively reference libraries in different projects"() {
  207. given:
  208. def app = new ExeWithLibraryUsingLibraryHelloWorldApp()
  209. app.writeSources(file("exe/src/main"), file("lib/src/hello"), file("greet/src/greetings"))
  210. and:
  211. settingsFile.text = "include ':exe', ':lib', ':greet'"
  212. buildFile << """
  213. project(":exe") {
  214. model {
  215. components {
  216. main(NativeExecutableSpec) {
  217. sources {
  218. cpp.lib project: ':lib', library: 'hello'
  219. }
  220. }
  221. }
  222. }
  223. }
  224. project(":lib") {
  225. model {
  226. components {
  227. hello(NativeLibrarySpec) {
  228. sources {
  229. cpp.lib project: ':greet', library: 'greetings', linkage: 'static'
  230. }
  231. }
  232. }
  233. }
  234. }
  235. project(":greet") {
  236. model {
  237. components {
  238. greetings(NativeLibrarySpec)
  239. }
  240. }
  241. }
  242. """
  243. when:
  244. succeeds ":exe:installMainExecutable"
  245. then:
  246. installation("exe/build/install/mainExecutable").exec().out == app.englishOutput
  247. }
  248. def "can have component graph with project dependency cycle"() {
  249. given:
  250. def app = new ExeWithLibraryUsingLibraryHelloWorldApp()
  251. app.writeSources(file("exe/src/main"), file("lib/src/hello"), file("exe/src/greetings"))
  252. and:
  253. settingsFile.text = "include ':exe', ':lib'"
  254. buildFile << """
  255. project(":exe") {
  256. apply plugin: "cpp"
  257. model {
  258. components {
  259. main(NativeExecutableSpec) {
  260. sources {
  261. cpp.lib project: ':lib', library: 'hello'
  262. }
  263. }
  264. greetings(NativeLibrarySpec)
  265. }
  266. }
  267. }
  268. project(":lib") {
  269. apply plugin: "cpp"
  270. model {
  271. components {
  272. hello(NativeLibrarySpec) {
  273. sources {
  274. cpp.lib project: ':exe', library: 'greetings', linkage: 'static'
  275. }
  276. }
  277. }
  278. }
  279. }
  280. """
  281. when:
  282. succeeds ":exe:installMainExecutable"
  283. then:
  284. installation("exe/build/install/mainExecutable").exec().out == app.englishOutput
  285. }
  286. def "can have component graph with diamond dependency"() {
  287. given:
  288. def app = new ExeWithDiamondDependencyHelloWorldApp()
  289. app.writeSources(file("src/main"), file("src/hello"), file("src/greetings"))
  290. and:
  291. buildFile << """
  292. apply plugin: "cpp"
  293. model {
  294. components {
  295. main(NativeExecutableSpec) {
  296. sources {
  297. cpp.lib library: "hello"
  298. cpp.lib library: "greetings", linkage: "static"
  299. }
  300. }
  301. hello(NativeLibrarySpec) {
  302. sources {
  303. cpp.lib library: "greetings", linkage: "static"
  304. }
  305. }
  306. greetings(NativeLibrarySpec)
  307. }
  308. }
  309. """
  310. when:
  311. succeeds "installMainExecutable"
  312. then:
  313. installation("build/install/mainExecutable").exec().out == app.englishOutput
  314. and:
  315. notExecuted ":greetingsSharedLibrary"
  316. sharedLibrary("build/binaries/greetingsSharedLibrary/greetings").assertDoesNotExist()
  317. }
  318. def "can have component graph with both static and shared variants of same library"() {
  319. given:
  320. def app = new ExeWithDiamondDependencyHelloWorldApp()
  321. app.writeSources(file("src/main"), file("src/hello"), file("src/greetings"))
  322. and:
  323. buildFile << """
  324. apply plugin: "cpp"
  325. model {
  326. components {
  327. main(NativeExecutableSpec) {
  328. sources {
  329. cpp.lib library: "hello", linkage: "shared"
  330. cpp.lib library: "greetings", linkage: "shared"
  331. }
  332. }
  333. hello(NativeLibrarySpec) {
  334. sources {
  335. cpp.lib library: "greetings", linkage: "static"
  336. }
  337. }
  338. greetings(NativeLibrarySpec)
  339. }
  340. }
  341. """
  342. when:
  343. succeeds "installMainExecutable"
  344. then:
  345. installation("build/install/mainExecutable").exec().out == app.englishOutput
  346. and:
  347. executedAndNotSkipped ":greetingsSharedLibrary", ":greetingsStaticLibrary"
  348. sharedLibrary("build/binaries/greetingsSharedLibrary/greetings").assertExists()
  349. staticLibrary("build/binaries/greetingsStaticLibrary/greetings").assertExists()
  350. and:
  351. println executable("build/binaries/mainExecutable/main").binaryInfo.listLinkedLibraries()
  352. println sharedLibrary("build/binaries/helloSharedLibrary/hello").binaryInfo.listLinkedLibraries()
  353. }
  354. }