├── .github └── workflows │ ├── linux.yml │ ├── macos.yml │ └── windows.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── build.rs ├── notes.md ├── src └── main.rs └── wstest ├── .cargo └── config ├── Cargo.lock ├── Cargo.toml ├── foo ├── Cargo.toml └── src │ └── lib.rs ├── run.sh └── wstest ├── Cargo.toml ├── README.md ├── build.rs └── src └── main.rs /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: Linux 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: "35 2 * * *" 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Run cargo-vcpkg integration tests 16 | run: wstest/run.sh 17 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: "35 2 * * *" 8 | jobs: 9 | build: 10 | runs-on: macos-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Run cargo-vcpkg integration tests 15 | run: wstest/run.sh 16 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: "35 7 * * *" # UTC 8 | 9 | jobs: 10 | build: 11 | runs-on: windows-2019 12 | strategy: 13 | matrix: 14 | config: 15 | - { 16 | target: "x86_64-pc-windows-msvc", 17 | VCPKG_DEFAULT_TRIPLET: "x64-windows-static", 18 | RUSTFLAGS: "-Ctarget-feature=+crt-static", 19 | } 20 | - { 21 | target: "x86_64-pc-windows-msvc", 22 | VCPKG_DEFAULT_TRIPLET: "x64-windows-static-md", 23 | } 24 | - { 25 | target: "x86_64-pc-windows-msvc", 26 | VCPKG_DEFAULT_TRIPLET: "x64-windows", 27 | VCPKGRS_DYNAMIC: 1, 28 | } 29 | - { 30 | target: "i686-pc-windows-msvc", 31 | VCPKG_DEFAULT_TRIPLET: "x86-windows-static", 32 | RUSTFLAGS: "-Ctarget-feature=+crt-static", 33 | } 34 | - { 35 | target: "i686-pc-windows-msvc", 36 | VCPKG_DEFAULT_TRIPLET: "x86-windows-static-md", 37 | } 38 | - { 39 | target: "i686-pc-windows-msvc", 40 | VCPKG_DEFAULT_TRIPLET: "x86-windows", 41 | VCPKGRS_DYNAMIC: 1, 42 | } 43 | fail-fast: false 44 | steps: 45 | - uses: actions/checkout@v2 46 | - name: Run cargo-vcpkg integration tests 47 | shell: bash 48 | run: wstest/run.sh 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .vscode/ 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog for cargo-vcpkg 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html) as implemented by Cargo. 7 | 8 | ## [0.1.7] - 2022-11-11 9 | 10 | ### Added 11 | 12 | - Support for backend vcpkg build configuration using [overlay triplets](https://github.com/mcgoo/cargo-vcpkg#overlay-triplets). Thanks @pkgw! 13 | 14 | ## [0.1.6] - 2021-06-12 15 | 16 | ### Changed 17 | 18 | - Released from new home mcgoo/cargo-vcpkg. 19 | 20 | ### Fixes 21 | 22 | - `./target/vcpkg` may not have been getting refreshed properly when tracking branches when running `cargo vcpkg build`. 23 | - Warnings addressed for newer releases of rust. 24 | 25 | ## [0.1.5] - 2020-06-10 26 | 27 | ### Fixes 28 | 29 | - Fixes 'dev-dependencies' key handling for 'target' settings. 30 | 31 | ## [0.1.4] - 2020-06-10 32 | 33 | ### Added 34 | 35 | - Added 'dev-dependencies' key in [package.metadata.vcpkg] to allow installing 36 | additional packages for development and testing without requiring the end user to 37 | build those packages. 38 | 39 | ### Changed 40 | 41 | - Changed 'install' key in [package.metadata.vcpkg] to 'dependencies'. ('install' continues to work.) 42 | 43 | ## [0.1.3] - 2020-06-04 44 | 45 | ### Added 46 | 47 | - On macOS, if Apple clang 11 or later is available, try to bootstrap vcpkg with it first. If this fails, the build will be retried, which will require another compiler. 48 | 49 | ## [0.1.2] - 2020-06-01 50 | 51 | ### Fixed 52 | 53 | - Fixed help when running under cargo. 54 | - Added pull a step when using a branch so the branch tracks the remote 55 | correctly. 56 | 57 | ### Added 58 | 59 | - Display names of packages as they are being built. 60 | - Added some more useful information to the error that is displayed 61 | if there is no vcpkg metadata in the root crate. 62 | 63 | ## [0.1.1] - 2020-06-01 64 | 65 | ### Fixed 66 | 67 | - Fixed building from a cmd.exe shell on Windows. 68 | 69 | ## [0.1.0] - 2020-05-31 70 | 71 | ### Added 72 | 73 | - Initial release 74 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ansi_term" 7 | version = "0.11.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 10 | dependencies = [ 11 | "winapi", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.31" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f" 19 | 20 | [[package]] 21 | name = "atty" 22 | version = "0.2.14" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 25 | dependencies = [ 26 | "hermit-abi", 27 | "libc", 28 | "winapi", 29 | ] 30 | 31 | [[package]] 32 | name = "autocfg" 33 | version = "1.0.1" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 36 | 37 | [[package]] 38 | name = "bitflags" 39 | version = "1.0.3" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" 42 | 43 | [[package]] 44 | name = "camino" 45 | version = "1.0.4" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "d4648c6d00a709aa069a236adcaae4f605a6241c72bf5bee79331a4b625921a9" 48 | dependencies = [ 49 | "serde", 50 | ] 51 | 52 | [[package]] 53 | name = "cargo-platform" 54 | version = "0.1.1" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "0226944a63d1bf35a3b5f948dd7c59e263db83695c9e8bffc4037de02e30f1d7" 57 | dependencies = [ 58 | "serde", 59 | ] 60 | 61 | [[package]] 62 | name = "cargo-vcpkg" 63 | version = "0.1.6" 64 | dependencies = [ 65 | "anyhow", 66 | "cargo_metadata", 67 | "remove_dir_all", 68 | "serde", 69 | "serde_json", 70 | "structopt", 71 | "termcolor", 72 | "vcpkg", 73 | ] 74 | 75 | [[package]] 76 | name = "cargo_metadata" 77 | version = "0.13.1" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8" 80 | dependencies = [ 81 | "camino", 82 | "cargo-platform", 83 | "semver", 84 | "semver-parser", 85 | "serde", 86 | "serde_json", 87 | ] 88 | 89 | [[package]] 90 | name = "cfg-if" 91 | version = "0.1.10" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 94 | 95 | [[package]] 96 | name = "cfg-if" 97 | version = "1.0.0" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 100 | 101 | [[package]] 102 | name = "clap" 103 | version = "2.33.1" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" 106 | dependencies = [ 107 | "ansi_term", 108 | "atty", 109 | "bitflags", 110 | "strsim", 111 | "textwrap", 112 | "unicode-width", 113 | "vec_map", 114 | ] 115 | 116 | [[package]] 117 | name = "const_fn" 118 | version = "0.4.5" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" 121 | 122 | [[package]] 123 | name = "crossbeam-channel" 124 | version = "0.5.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" 127 | dependencies = [ 128 | "cfg-if 1.0.0", 129 | "crossbeam-utils", 130 | ] 131 | 132 | [[package]] 133 | name = "crossbeam-deque" 134 | version = "0.8.0" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" 137 | dependencies = [ 138 | "cfg-if 1.0.0", 139 | "crossbeam-epoch", 140 | "crossbeam-utils", 141 | ] 142 | 143 | [[package]] 144 | name = "crossbeam-epoch" 145 | version = "0.9.1" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" 148 | dependencies = [ 149 | "cfg-if 1.0.0", 150 | "const_fn", 151 | "crossbeam-utils", 152 | "lazy_static", 153 | "memoffset", 154 | "scopeguard", 155 | ] 156 | 157 | [[package]] 158 | name = "crossbeam-utils" 159 | version = "0.8.1" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" 162 | dependencies = [ 163 | "autocfg", 164 | "cfg-if 1.0.0", 165 | "lazy_static", 166 | ] 167 | 168 | [[package]] 169 | name = "either" 170 | version = "1.6.1" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 173 | 174 | [[package]] 175 | name = "heck" 176 | version = "0.3.1" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 179 | dependencies = [ 180 | "unicode-segmentation", 181 | ] 182 | 183 | [[package]] 184 | name = "hermit-abi" 185 | version = "0.1.13" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" 188 | dependencies = [ 189 | "libc", 190 | ] 191 | 192 | [[package]] 193 | name = "itoa" 194 | version = "0.4.5" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" 197 | 198 | [[package]] 199 | name = "lazy_static" 200 | version = "1.4.0" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 203 | 204 | [[package]] 205 | name = "libc" 206 | version = "0.2.71" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" 209 | 210 | [[package]] 211 | name = "log" 212 | version = "0.4.13" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" 215 | dependencies = [ 216 | "cfg-if 0.1.10", 217 | ] 218 | 219 | [[package]] 220 | name = "memoffset" 221 | version = "0.6.1" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" 224 | dependencies = [ 225 | "autocfg", 226 | ] 227 | 228 | [[package]] 229 | name = "num_cpus" 230 | version = "1.13.0" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 233 | dependencies = [ 234 | "hermit-abi", 235 | "libc", 236 | ] 237 | 238 | [[package]] 239 | name = "pest" 240 | version = "2.1.3" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" 243 | dependencies = [ 244 | "ucd-trie", 245 | ] 246 | 247 | [[package]] 248 | name = "proc-macro-error" 249 | version = "0.4.12" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" 252 | dependencies = [ 253 | "proc-macro-error-attr", 254 | "proc-macro2", 255 | "quote", 256 | "syn", 257 | "version_check", 258 | ] 259 | 260 | [[package]] 261 | name = "proc-macro-error-attr" 262 | version = "0.4.12" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" 265 | dependencies = [ 266 | "proc-macro2", 267 | "quote", 268 | "syn", 269 | "syn-mid", 270 | "version_check", 271 | ] 272 | 273 | [[package]] 274 | name = "proc-macro2" 275 | version = "1.0.15" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "70a50b9351bfa8d65a7d93ce712dc63d2fd15ddbf2c36990fc7cac344859c04f" 278 | dependencies = [ 279 | "unicode-xid", 280 | ] 281 | 282 | [[package]] 283 | name = "quote" 284 | version = "1.0.6" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" 287 | dependencies = [ 288 | "proc-macro2", 289 | ] 290 | 291 | [[package]] 292 | name = "rayon" 293 | version = "1.5.0" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" 296 | dependencies = [ 297 | "autocfg", 298 | "crossbeam-deque", 299 | "either", 300 | "rayon-core", 301 | ] 302 | 303 | [[package]] 304 | name = "rayon-core" 305 | version = "1.9.0" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" 308 | dependencies = [ 309 | "crossbeam-channel", 310 | "crossbeam-deque", 311 | "crossbeam-utils", 312 | "lazy_static", 313 | "num_cpus", 314 | ] 315 | 316 | [[package]] 317 | name = "remove_dir_all" 318 | version = "0.6.1" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "d7b19f5c2df95a07275e7224924cc62f76f04525f4fda801473f85e325e81977" 321 | dependencies = [ 322 | "log", 323 | "num_cpus", 324 | "rayon", 325 | "winapi", 326 | ] 327 | 328 | [[package]] 329 | name = "ryu" 330 | version = "1.0.4" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" 333 | 334 | [[package]] 335 | name = "scopeguard" 336 | version = "1.1.0" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 339 | 340 | [[package]] 341 | name = "semver" 342 | version = "0.11.0" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" 345 | dependencies = [ 346 | "semver-parser", 347 | "serde", 348 | ] 349 | 350 | [[package]] 351 | name = "semver-parser" 352 | version = "0.10.2" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" 355 | dependencies = [ 356 | "pest", 357 | ] 358 | 359 | [[package]] 360 | name = "serde" 361 | version = "1.0.110" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" 364 | dependencies = [ 365 | "serde_derive", 366 | ] 367 | 368 | [[package]] 369 | name = "serde_derive" 370 | version = "1.0.110" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" 373 | dependencies = [ 374 | "proc-macro2", 375 | "quote", 376 | "syn", 377 | ] 378 | 379 | [[package]] 380 | name = "serde_json" 381 | version = "1.0.61" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" 384 | dependencies = [ 385 | "itoa", 386 | "ryu", 387 | "serde", 388 | ] 389 | 390 | [[package]] 391 | name = "strsim" 392 | version = "0.8.0" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 395 | 396 | [[package]] 397 | name = "structopt" 398 | version = "0.3.7" 399 | source = "registry+https://github.com/rust-lang/crates.io-index" 400 | checksum = "884ae79d6aad1e738f4a70dff314203fd498490a63ebc4d03ea83323c40b7b72" 401 | dependencies = [ 402 | "clap", 403 | "structopt-derive", 404 | ] 405 | 406 | [[package]] 407 | name = "structopt-derive" 408 | version = "0.4.0" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "0a97f829a34a0a9d5b353a881025a23b8c9fd09d46be6045df6b22920dbd7a93" 411 | dependencies = [ 412 | "heck", 413 | "proc-macro-error", 414 | "proc-macro2", 415 | "quote", 416 | "syn", 417 | ] 418 | 419 | [[package]] 420 | name = "syn" 421 | version = "1.0.23" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "95b5f192649e48a5302a13f2feb224df883b98933222369e4b3b0fe2a5447269" 424 | dependencies = [ 425 | "proc-macro2", 426 | "quote", 427 | "unicode-xid", 428 | ] 429 | 430 | [[package]] 431 | name = "syn-mid" 432 | version = "0.5.0" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" 435 | dependencies = [ 436 | "proc-macro2", 437 | "quote", 438 | "syn", 439 | ] 440 | 441 | [[package]] 442 | name = "termcolor" 443 | version = "1.1.0" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" 446 | dependencies = [ 447 | "winapi-util", 448 | ] 449 | 450 | [[package]] 451 | name = "textwrap" 452 | version = "0.11.0" 453 | source = "registry+https://github.com/rust-lang/crates.io-index" 454 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 455 | dependencies = [ 456 | "unicode-width", 457 | ] 458 | 459 | [[package]] 460 | name = "ucd-trie" 461 | version = "0.1.3" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" 464 | 465 | [[package]] 466 | name = "unicode-segmentation" 467 | version = "1.6.0" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" 470 | 471 | [[package]] 472 | name = "unicode-width" 473 | version = "0.1.5" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" 476 | 477 | [[package]] 478 | name = "unicode-xid" 479 | version = "0.2.0" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 482 | 483 | [[package]] 484 | name = "vcpkg" 485 | version = "0.2.11" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" 488 | 489 | [[package]] 490 | name = "vec_map" 491 | version = "0.8.1" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 494 | 495 | [[package]] 496 | name = "version_check" 497 | version = "0.9.2" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" 500 | 501 | [[package]] 502 | name = "winapi" 503 | version = "0.3.5" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" 506 | dependencies = [ 507 | "winapi-i686-pc-windows-gnu", 508 | "winapi-x86_64-pc-windows-gnu", 509 | ] 510 | 511 | [[package]] 512 | name = "winapi-i686-pc-windows-gnu" 513 | version = "0.4.0" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 516 | 517 | [[package]] 518 | name = "winapi-util" 519 | version = "0.1.5" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 522 | dependencies = [ 523 | "winapi", 524 | ] 525 | 526 | [[package]] 527 | name = "winapi-x86_64-pc-windows-gnu" 528 | version = "0.4.0" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 531 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cargo-vcpkg" 3 | version = "0.1.7" 4 | authors = ["Jim McGrath "] 5 | edition = "2018" 6 | license = "MIT/Apache-2.0" 7 | repository = "https://github.com/mcgoo/cargo-vcpkg" 8 | readme = "README.md" 9 | documentation = "https://docs.rs/vcpkg" 10 | description = """ 11 | A cargo subcommand to build a vcpkg tree from metadata entries in Cargo.toml for 12 | a top level crate and the crates that it depends on. 13 | """ 14 | keywords = ["build-dependencies", "windows", "macos", "linux"] 15 | categories = ["development-tools::cargo-plugins"] 16 | 17 | [dev-dependencies] 18 | remove_dir_all = "0.6.0" 19 | 20 | [dependencies] 21 | anyhow = "1.0.31" 22 | cargo_metadata = "0.13.0" 23 | serde = { version = "1.0", features = ["derive"] } 24 | serde_json = "1.0.53" 25 | structopt = "0.3" 26 | termcolor = "1.1.0" 27 | vcpkg = "0.2.11" 28 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Jim McGrath 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cargo-vcpkg [![Windows](https://github.com/mcgoo/vcpkg-rs/workflows/Windows/badge.svg?branch=master)](https://github.com/mcgoo/vcpkg-rs/actions?query=workflow%3AWindows) [![macOS](https://github.com/mcgoo/vcpkg-rs/workflows/macOS/badge.svg?branch=master)](https://github.com/mcgoo/vcpkg-rs/actions?query=workflow%3AmacOS) [![Linux](https://github.com/mcgoo/vcpkg-rs/workflows/Linux/badge.svg?branch=master)](https://github.com/mcgoo/vcpkg-rs/actions?query=workflow%3ALinux) 2 | 3 | [Changelog](https://github.com/mcgoo/cargo-vcpkg/blob/master/CHANGELOG.md) 4 | 5 | This command `cargo vcpkg` will create a [vcpkg](https://github.com/microsoft/vcpkg) tree and install the packages specified in `Cargo.toml` files in the crate being built and crates it depends on. Crates that use the [vcpkg crate](https://crates.io/crates/vcpkg) will be able to find libraries automatically. 6 | 7 | ## Example 8 | 9 | ```toml 10 | [package.metadata.vcpkg] 11 | git = "https://github.com/microsoft/vcpkg" 12 | rev = "4c1db68" 13 | dependencies = ["pkg1", "pkg2"] 14 | ``` 15 | 16 | ``` 17 | $ cargo install cargo-vcpkg 18 | $ cargo vcpkg build 19 | Fetching vcpkg 20 | Checkout rev/tag/branch 4c1db68 21 | Compiling pkg1, pkg2 22 | Finished in 1.93s 23 | $ cargo build 24 | [...] 25 | ``` 26 | 27 | ## Per target configuration 28 | 29 | It is also possible to install different sets of packages per target, and override the vcpkg triplet to install. 30 | 31 | ```toml 32 | [package.metadata.vcpkg] 33 | git = "https://github.com/microsoft/vcpkg" 34 | rev = "4c1db68" 35 | dependencies = ["sdl2"] 36 | 37 | [package.metadata.vcpkg.target] 38 | x86_64-apple-darwin = { dependencies = ["sdl2", "sdl2-gfx" ] } 39 | x86_64-unknown-linux-gnu = { dependencies = ["sdl2", "opencv"] } 40 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static", dependencies = ["sdl2", "zeromq"] } 41 | ``` 42 | 43 | ## Development dependencies 44 | 45 | Setting the `dev-dependencies` key allows building libraries that are required by binaries in this crate. Only the packages in the `dependencies` key will be installed if `cargo vcpkg` is run on a crate that depends on this crate. 46 | 47 | ```toml 48 | [package.metadata.vcpkg] 49 | git = "https://github.com/microsoft/vcpkg" 50 | rev = "4c1db68" 51 | dependencies = ["sdl2"] 52 | dev-dependencies = ["sdl2-image"] 53 | 54 | [package.metadata.vcpkg.target] 55 | x86_64-apple-darwin = { dev-dependencies = ["sdl2-gfx" ] } 56 | ``` 57 | 58 | ## Overlay triplets 59 | 60 | Setting the `overlay-triplets-path` key allows you use custom [triplet files] in 61 | your build. The value of this key should be the path to a directory containing 62 | triplet files. These files will be made available during the vcpkg build through 63 | its `--overlay-triplets` argument. 64 | 65 | [triplet files]: https://vcpkg.readthedocs.io/en/latest/users/triplets/ 66 | 67 | ```toml 68 | [package.metadata.vcpkg] 69 | git = "https://github.com/microsoft/vcpkg" 70 | rev = "4c1db68" 71 | dependencies = ["sdl2"] 72 | overlay-triplets-path = "support/custom-triplets" 73 | 74 | [package.metadata.vcpkg.target] 75 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-release" } 76 | ``` 77 | 78 | Here, the repository should contain a file named 79 | `support/custom-triplets/x64-windows-static-release.cmake`. 80 | 81 | ## Installation 82 | 83 | Install by running 84 | 85 | ``` 86 | cargo install cargo-vcpkg 87 | ``` 88 | crates.io/vcpkg needs older Rust for compatibility with older projects, while cargo-vcpkg would like to track new versions for the latest features in Cargo.toml, hense the split of repos between components. 89 | 90 | ## License 91 | 92 | See LICENSE-APACHE, and LICENSE-MIT for details. 93 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!( 3 | "cargo:rustc-env=TARGET={}", 4 | std::env::var("TARGET").unwrap() 5 | ); 6 | } 7 | -------------------------------------------------------------------------------- /notes.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | 3 | ## Making a release 4 | 5 | 1. `cargo test` 6 | 1. run `./wstest/run.sh` as local integration test. 7 | 1. check that everything is committed and work dir is clean 8 | 1. push to master on github 9 | 1. check that github actions ci passes 10 | 1. update changelog, commit and push 11 | 1. update version number in Cargo.toml for the crate to be released 12 | 1. commit 13 | 1. push 14 | 1. wait for the ci to work 15 | 1. create a tag for the crate like `git tag cargo-vcpkg-0.1.5` 16 | 1. cd to the crate dir and run `cargo publish` 17 | 1. git push origin --tags 18 | 19 | ## Possible future features 20 | 21 | - hide or deprecate or note that the lib_name api is not as good as find_package 22 | 23 | - make sure the find_package api is first in the docs and mention that it's the best option 24 | 25 | - allow specifying a triple to use using an environment variable. this will allow setting up a custom "x64-rust-static" triple that dynamically links to msvcrt, allowing static builds with the default rust. 26 | 27 | - add information about target triples and target triple selection being driven by RUSTFLAGS=-Ctarget-feature=+crt-static 28 | 29 | - add a note that even rust debug builds are linked against the release version 30 | of built libraries 31 | 32 | - there is a lib\no_auto_link folder that some packages generate that needs 33 | to be added to the link line. this will require finding an example of 34 | a library that uses that feature. (boost?) 35 | 36 | - vcpkg_cli: make probe failure return a nonzero exit code so the build fails 37 | 38 | - remove crate doc info about the libname -> package mapping. (why?) 39 | 40 | - look into the possibility of using dotenv to allow setting VCPKG_ROOT 41 | 42 | - could run vcpkg and parse it's output to determine what package versions are installed. 43 | 44 | - could parse vcpkg's installed files list to guess at the names for libraries and dlls rather than requiring them to be specified. 45 | 46 | - could parse vcpkg's installed packages list to determine what other packages we need to link against. 47 | 48 | - vcpkg has common include and lib dirs so there is a chance that someone is going to end up picking up a vcpkg lib on their link line in preference to some other version at some point. I believe cmake handles this by using absolute paths for libs wherever possible. if everything below you in the dependency tree is looking in vcpkg then everything will agree. 49 | 50 | - vcpkg has a per-package output dir that looks like it would be helpful, but at present it is undocumented and subject to change. (what I read mentioned the possibility of compressing the contents.) 51 | 52 | - warn if you use something that looks like a vcpkg triplet in place of a rust triple 53 | 54 | - allow specifying of the library to be installed like pkg-config does. (hard in general because there is no specific format for version numbers ) 55 | 56 | - allow stipulating that a specific feature be installed. at present if a feature is installed any extra libraries it requires will be linked as expected. how should this be? The vcpkg way is to specify it as harfbuzz[graphite2,icu] for example. 57 | 58 | - report enabled/available features in the Library returned from find_package 59 | 60 | - get information about installed packages by running the vcpkg executable 61 | 62 | - if using json to encode the information, this requires writing a json parser or adding a dependency on serde for anything that transitively depends on vcpkg, which is a lot of stuff, probably only a tiny percentage of which actually uses the vcpkg functionality. otherwise, could invent yet another easy-to-parse custom format. 63 | - vcpkg is now available on linux and macos also. a possible use is to build the whole bag of windows dependencies on a windows machine at the point that lld can cross link windows/msvc code. 64 | 65 | - add a changelog for vcpkg_cli 66 | 67 | - make the breaking change of dropping Rust 1.10 compatibility when updating to 0.3 68 | 69 | - vcpkg_cli should say if there are other versions of the ports available that do not match what is being looked for 70 | 71 | - add some commentary describing the vcpkg target triplets on windows - static vs dynamic crt and the fact that rust prefers something in between - dynamic crt, static libs on top of that. 72 | 73 | - vcpkg now has a community supported triplet called x64-windows-static-md which is a match for the default Rust build type on windows - dynamic linking to the c runtime, and static linking to other libraries. 74 | 75 | - mention more clearly that vcpkg is only useful in build.rs and it should be added in build-dependencies 76 | 77 | - add a better error message than the spurious NotMSVC if find_package gets run from an app rather than in build.rs 78 | 79 | ## Creating empty files from list files 80 | 81 | ```sh 82 | touch `grep -h \.lib$ vcpkg/info/*x86* | grep -v debug ` 83 | touch `grep -h \.dll$ vcpkg/info/*x86* | grep -v debug ` 84 | ``` 85 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{bail, Context}; 2 | //use indicatif::{ProgressBar, ProgressStyle}; 3 | use serde::Deserialize; 4 | use std::{ 5 | collections::BTreeMap, 6 | ffi::OsString, 7 | fs::{canonicalize, File}, 8 | io::{BufRead, BufReader, Cursor, Write}, 9 | process::{Command, Output, Stdio}, 10 | str, 11 | time::SystemTime, 12 | }; 13 | use structopt::StructOpt; 14 | use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; 15 | use vcpkg::{find_vcpkg_root, Config}; 16 | 17 | // settings for a specific Rust target 18 | #[derive(Debug, Deserialize)] 19 | #[serde(rename_all = "kebab-case")] 20 | struct Target { 21 | triplet: Option, 22 | // this dependencies key for a specific target overrides the main entry 23 | // so a the target can opt out of installing packages 24 | #[serde(alias = "install")] 25 | dependencies: Option>, 26 | dev_dependencies: Option>, 27 | } 28 | 29 | #[derive(Debug, Deserialize)] 30 | #[serde(rename_all = "kebab-case")] 31 | struct Vcpkg { 32 | // vcpkg_root: Option, 33 | #[serde(default = "BTreeMap::new")] 34 | target: BTreeMap, 35 | branch: Option, 36 | rev: Option, 37 | git: Option, 38 | tag: Option, 39 | 40 | #[serde(alias = "install")] 41 | dependencies: Option>, 42 | dev_dependencies: Option>, 43 | 44 | overlay_triplets_path: Option, 45 | 46 | // Was this ever used?? 47 | #[allow(dead_code)] 48 | build_type: Option, 49 | } 50 | 51 | #[derive(Debug, Deserialize)] 52 | struct Metadata { 53 | vcpkg: Vcpkg, 54 | } 55 | 56 | #[derive(Debug, PartialEq, StructOpt)] 57 | /// Install vcpkg and build packages 58 | /// 59 | /// This program clones vcpkg from the specified source and 60 | /// compiles it. It then builds packages required by crates 61 | /// that are depended on by the top level crate being built. 62 | #[structopt(rename_all = "kebab-case")] 63 | struct Opt { 64 | /// Display more information while building 65 | /// 66 | /// This will display the output of git and 67 | /// vcpkg operations. 68 | #[structopt(short, long)] 69 | verbose: bool, 70 | 71 | // #[structopt(long)] 72 | // manifest_path: Option, 73 | #[structopt(subcommand)] 74 | sub: Subcommands, 75 | } 76 | 77 | #[derive(Debug, PartialEq, StructOpt)] 78 | enum Subcommands { 79 | /// Build packages, checking out the correct version 80 | /// 81 | /// This command will clone or update a vcpkg tree to the version specified 82 | /// in Cargo.toml and build the required packages. 83 | Build { 84 | #[structopt(long)] 85 | /// Path to Cargo.toml 86 | manifest_path: Option, 87 | 88 | #[structopt(long)] 89 | /// Build for the target triple 90 | target: Option, 91 | }, 92 | // `external_subcommand` tells structopt to put 93 | // all the extra arguments into this Vec 94 | // #[structopt(external_subcommand)] 95 | // Cargo(Vec), 96 | } 97 | 98 | #[derive(Debug)] 99 | enum RevSelector { 100 | Rev(String), 101 | Tag(String), 102 | Branch(String), 103 | } 104 | 105 | fn main() { 106 | // cargo passes us the "vcpkg" arg when it calls us. Drop it before 107 | // parsing the arg list so it doesn't end up the usage description 108 | let mut args = std::env::args().collect::>(); 109 | if args.len() >= 2 && args[1] == "vcpkg" { 110 | args.remove(1); 111 | } 112 | let args = Opt::from_iter(args); 113 | 114 | match args.sub { 115 | Subcommands::Build { .. } => { 116 | build(args).unwrap_or_else(|e| { 117 | eprintln!("cargo-vcpkg: {}", e); 118 | std::process::exit(1); 119 | }); 120 | } 121 | } 122 | } 123 | 124 | fn build(opt: Opt) -> Result<(), anyhow::Error> { 125 | let start_time = SystemTime::now(); 126 | 127 | let target_triple = target_triple(); 128 | 129 | let verbose = opt.verbose; 130 | 131 | let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path")); 132 | let mut cmd = cargo_metadata::MetadataCommand::new(); 133 | 134 | match args.next() { 135 | Some(p) if p == "--manifest-path" => { 136 | cmd.manifest_path(args.next().unwrap()); 137 | } 138 | Some(p) => { 139 | cmd.manifest_path(p.trim_start_matches("--manifest-path=")); 140 | } 141 | None => {} 142 | } 143 | let metadata = cmd.exec()?; 144 | 145 | let vmd = process_metadata(&metadata, &target_triple)?; 146 | 147 | // should we modify the existing? 148 | // let mut allow_updates = true; 149 | 150 | // find the vcpkg root 151 | let vcpkg_root = find_vcpkg_root(&Config::default()).unwrap_or_else(|_| { 152 | let target_directory = metadata.target_directory.clone(); 153 | let mut vcpkg_root = target_directory; 154 | vcpkg_root.push("vcpkg"); 155 | vcpkg_root.into() 156 | }); 157 | if verbose { 158 | println!("vcpkg root is {}", vcpkg_root.display()); 159 | } 160 | // if it does not exist, clone vcpkg from git 161 | let mut vcpkg_root_file = vcpkg_root.clone(); 162 | vcpkg_root_file.push(".vcpkg-root"); 163 | if !vcpkg_root_file.exists() { 164 | let git_url = vmd.git_url.context(format!( 165 | "could not find a vcpkg installation and crate \n\ 166 | {} does not specify a git repository to clone from. \n\n\ 167 | Add a [package.metadata.vcpkg] section to the root crate's\n\ 168 | Cargo.toml, and add a 'git' key and one of the 'branch',\n\ 169 | 'tag' or 'rev' keys to tell this program where to get\n\ 170 | the correct version of vcpkg from. For example:\n\n\ 171 | [package.metadata.vcpkg]\n\ 172 | git = \"https://github.com/microsoft/vcpkg\"\n\ 173 | branch = \"master\" ", 174 | vmd.root_crate 175 | ))?; 176 | print_tag("Cloning", &git_url); 177 | let mut cmd = Command::new("git"); 178 | cmd.arg("clone"); 179 | cmd.arg(git_url); 180 | cmd.arg(&vcpkg_root); 181 | let _output = run_command(cmd, verbose).context("failed to run git clone")?; 182 | 183 | //eprintln!("git clone done = {:?}", output.status); 184 | } else { 185 | print_tag("Fetching", "vcpkg"); 186 | let mut cmd = Command::new("git"); 187 | cmd.arg("fetch"); 188 | cmd.arg("--verbose"); 189 | cmd.arg("--all"); 190 | cmd.current_dir(&vcpkg_root); 191 | let output = run_command(cmd, verbose).context("failed to run git fetch")?; 192 | 193 | if !output.status.success() { 194 | bail!("fetch failed"); 195 | } 196 | } 197 | 198 | // create a cargo-vcpkg.toml in the vcpkg tree 199 | let mut cargo_vcpkg_config_file = vcpkg_root.clone(); 200 | cargo_vcpkg_config_file.push("downloads"); 201 | std::fs::create_dir_all(&cargo_vcpkg_config_file) 202 | .context("could not create downloads directory in vcpkg tree")?; 203 | cargo_vcpkg_config_file.push("cargo-vcpkg.toml"); 204 | if !cargo_vcpkg_config_file.exists() { 205 | let mut file = 206 | File::create(cargo_vcpkg_config_file).context("could not create cargo-vcpkg.toml")?; 207 | file.write_all(b"# This file was created automatically by cargo-vcpkg\n")?; 208 | } 209 | 210 | // check out the required rev 211 | let rev_tag_branch = vmd.rev_tag_branch.ok_or_else(|| { 212 | anyhow::anyhow!("did not find vcpkg Cargo metadata with branch/rev/tag for git source") 213 | })?; 214 | let (desc, rev_tag_branch, do_pull) = match rev_tag_branch { 215 | RevSelector::Rev(r) => ("rev", r, false), 216 | RevSelector::Tag(t) => ("tag", t, false), //? 217 | RevSelector::Branch(b) => ("branch", b, true), 218 | }; 219 | print_tag("Checkout", &format!("{} {}", desc, rev_tag_branch)); 220 | let mut cmd = Command::new("git"); 221 | cmd.arg("checkout"); 222 | cmd.arg(&rev_tag_branch); 223 | cmd.current_dir(&vcpkg_root); 224 | run_command(cmd, verbose).context("failed to execute process")?; 225 | 226 | // if it is a branch, run a git pull to move to the correct commit 227 | if do_pull { 228 | print_tag("Pulling", &format!("{} {}", desc, rev_tag_branch)); 229 | let mut cmd = Command::new("git"); 230 | cmd.arg("pull"); 231 | //cmd.arg(rev_tag_branch); 232 | cmd.current_dir(&vcpkg_root); 233 | run_command(cmd, verbose).context("failed to execute process")?; 234 | } 235 | // try and run 'vcpkg update' and if it fails or gives the version warning, rebuild it 236 | let require_bootstrap = match vcpkg_command(&vcpkg_root, &vmd.vcpkg_triplet) 237 | .arg("update") 238 | .output() 239 | { 240 | Ok(output) => { 241 | if verbose { 242 | println!("-- stdout --\n{}", String::from_utf8_lossy(&output.stdout)); 243 | println!("-- stderr --\n{}", String::from_utf8_lossy(&output.stderr)); 244 | println!("{:?}", output.status); 245 | } 246 | !output.status.success() 247 | || str::from_utf8(&output.stdout) 248 | .unwrap() 249 | .contains("Warning: Different source is available for vcpkg") 250 | } 251 | Err(_) => true, 252 | }; 253 | 254 | if require_bootstrap { 255 | run_bootstrap(&vcpkg_root, verbose)?; 256 | } 257 | 258 | // TODO: upgrade anything that is installed 259 | print_tag("Installing", &vmd.vcpkg_ports.join(" ")); 260 | let mut v = vcpkg_command(&vcpkg_root, &vmd.vcpkg_triplet); 261 | 262 | if let Some(otp) = vmd.overlay_triplets_path { 263 | // the vcpkg command is run from the vcpkg root directory, so we need to 264 | // resolve the overlay path since it's probably relative. 265 | let mut otarg = OsString::new(); 266 | otarg.push("--overlay-triplets="); 267 | otarg.push(canonicalize(otp).context("could not canonicalize overlay-triplets-path")?); 268 | v.arg(otarg); 269 | } 270 | 271 | v.arg("install"); 272 | v.arg("--recurse"); 273 | v.args(vmd.vcpkg_ports.as_slice()); 274 | v.stdout(Stdio::piped()); 275 | 276 | let mut output = v.spawn()?; 277 | 278 | let reader = BufReader::new(output.stdout.take().context("could not get stdout")?); 279 | 280 | // let style = ProgressStyle::default_bar() 281 | // .progress_chars("=> ") 282 | // .template(" Building [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg}"); 283 | // let bar = ProgressBar::new(10).with_style(style); 284 | for line in reader.lines().flat_map(Result::ok) { 285 | if let Some((pkg, triplet, _num, _tot)) = parse_build_line(&line) { 286 | print_tag("Compiling", &format!("{} (triplet {})", pkg, triplet)) 287 | } 288 | 289 | if verbose { 290 | println!("{}", line); 291 | } 292 | // bar.set_length(tot); 293 | // bar.set_position(num); 294 | // Building [==============================================> ] 58/59 295 | } 296 | // grab anything that is left 297 | let output = output.wait_with_output()?; 298 | 299 | if !output.status.success() { 300 | if !verbose { 301 | println!("-- stdout --\n{}", String::from_utf8_lossy(&output.stdout)); 302 | println!("-- stderr --\n{}", String::from_utf8_lossy(&output.stderr)); 303 | } 304 | bail!("failed"); 305 | } 306 | 307 | let duration = SystemTime::now().duration_since(start_time).unwrap(); 308 | print_tag("Finished", &format!("in {:0.2}s", duration.as_secs_f32())); 309 | Ok(()) 310 | } 311 | 312 | #[derive(Debug)] 313 | struct VcpkgMetadata { 314 | pub git_url: Option, 315 | pub vcpkg_ports: Vec, 316 | pub rev_tag_branch: Option, 317 | pub vcpkg_triplet: Option, 318 | pub overlay_triplets_path: Option, 319 | pub root_crate: cargo_metadata::PackageId, 320 | } 321 | 322 | fn process_metadata( 323 | metadata: &cargo_metadata::Metadata, 324 | target_triple: &str, 325 | ) -> Result { 326 | let dep_graph = metadata.resolve.as_ref().unwrap(); 327 | let root_crate = dep_graph 328 | .root 329 | .as_ref() 330 | .context("cannot run on a virtual manifest, this command requires running against an actual package in this workspace.")?; 331 | 332 | let mut git_url = None; 333 | let mut vcpkg_ports = Vec::::new(); 334 | let mut rev_tag_branch: Option = None; 335 | let mut vcpkg_triplet = None; 336 | let mut overlay_triplets_path = None; 337 | 338 | // dbg!(&metadata.workspace_root); 339 | // dbg!(&metadata.workspace_metadata); 340 | for p in &metadata.packages { 341 | // println!("-------------"); 342 | // dbg!(&p); 343 | if let Ok(v) = serde_json::from_value::(p.metadata.clone()) { 344 | // dbg!(&v); 345 | let v = v.vcpkg; 346 | let is_root_crate = p.id == *root_crate; 347 | 348 | // only use git url and rev from the root crate 349 | if v.git.is_some() && is_root_crate { 350 | git_url = v.git; 351 | 352 | // TODO: check the target and use it's package set if required 353 | // TODO: get the correct target 354 | // TODO: make sure to pull if it's a branch 355 | rev_tag_branch = match (&v.branch, &v.tag, &v.rev) { 356 | (Some(b), None, None) => Some(RevSelector::Branch(b.into())), 357 | (None, Some(t), None) => Some(RevSelector::Tag(t.into())), 358 | (None, None, Some(r)) => Some(RevSelector::Rev(r.into())), 359 | _ => { 360 | bail!("must specify one of branch,rev,tag for git source"); 361 | } 362 | }; 363 | } 364 | 365 | // likewise for overlay settings 366 | if v.overlay_triplets_path.is_some() && is_root_crate { 367 | overlay_triplets_path = v.overlay_triplets_path; 368 | } 369 | 370 | // if there is specific configuration for the target and it has 371 | // a dependencies key, use that rather than the general dependencies key 372 | match v.target.get(target_triple) { 373 | Some(target) => { 374 | let deps = target.dependencies.as_ref().or(v.dependencies.as_ref()); 375 | if deps.is_some() { 376 | vcpkg_ports.extend_from_slice(deps.unwrap().as_slice()); 377 | } 378 | if is_root_crate && target.triplet.is_some() { 379 | vcpkg_triplet = target.triplet.clone(); 380 | } 381 | if is_root_crate { 382 | let dev_deps = target 383 | .dev_dependencies 384 | .as_ref() 385 | .or(v.dev_dependencies.as_ref()); 386 | if dev_deps.is_some() { 387 | vcpkg_ports.extend_from_slice(dev_deps.unwrap().as_slice()); 388 | } 389 | } 390 | } 391 | _ => { 392 | // not found or dependencies is empty 393 | if v.dependencies.is_some() { 394 | vcpkg_ports.extend_from_slice(&v.dependencies.as_ref().unwrap().as_slice()); 395 | } 396 | if is_root_crate && v.dev_dependencies.is_some() { 397 | vcpkg_ports 398 | .extend_from_slice(&v.dev_dependencies.as_ref().unwrap().as_slice()); 399 | } 400 | } 401 | } 402 | } 403 | } 404 | 405 | Ok(VcpkgMetadata { 406 | git_url, 407 | vcpkg_ports, 408 | rev_tag_branch, 409 | vcpkg_triplet, 410 | overlay_triplets_path, 411 | root_crate: root_crate.clone(), 412 | }) 413 | } 414 | 415 | fn target_triple() -> String { 416 | let mut args = std::env::args().skip_while(|val| !val.starts_with("--target")); 417 | match args.next() { 418 | Some(p) if p == "--target" => args.next().unwrap(), 419 | Some(p) => p.trim_start_matches("--target=").into(), 420 | // if target is unspecified, default to the architecture that this 421 | // cargo-vcpkg binary was built for 422 | None => std::env!("TARGET").into(), 423 | } 424 | } 425 | 426 | fn vcpkg_command(vcpkg_root: &std::path::Path, vcpkg_triplet: &Option) -> Command { 427 | let mut x = vcpkg_root.to_path_buf(); 428 | if cfg!(windows) { 429 | x.push("vcpkg.exe"); 430 | } else { 431 | x.push("vcpkg") 432 | } 433 | let mut command = Command::new(x); 434 | command.current_dir(&vcpkg_root); 435 | if let Some(triplet) = &vcpkg_triplet { 436 | command.arg("--triplet"); 437 | command.arg(triplet); 438 | } 439 | command 440 | } 441 | 442 | fn run_command(mut cmd: Command, verbose: bool) -> Result { 443 | if verbose { 444 | cmd.stdout(Stdio::inherit()); 445 | cmd.stderr(Stdio::inherit()); 446 | } 447 | let output = cmd.output()?; 448 | 449 | if !output.status.success() { 450 | if !verbose { 451 | println!("-- stdout --\n{}", String::from_utf8_lossy(&output.stdout)); 452 | println!("-- stderr --\n{}", String::from_utf8_lossy(&output.stderr)); 453 | } 454 | bail!("failed"); 455 | } 456 | 457 | Ok(output) 458 | } 459 | 460 | fn print_tag(tag: &str, detail: &str) { 461 | let mut stdout = StandardStream::stdout(ColorChoice::Auto); 462 | stdout 463 | .set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true)) 464 | .unwrap(); 465 | 466 | print!("{:>12} ", tag); 467 | stdout.reset().unwrap(); 468 | println!("{}", detail); 469 | } 470 | 471 | fn parse_build_line(line: &str) -> Option<(String, String, u64, u64)> { 472 | let line = Some(line) 473 | .filter(|line| line.starts_with("Starting package ")) 474 | .map(|line| line.trim_start_matches("Starting package ").to_string())?; 475 | 476 | let progress_and_pkg_trp = line.splitn(2, ':').collect::>(); 477 | if progress_and_pkg_trp.len() != 2 { 478 | return None; 479 | } 480 | 481 | let pkg_with_triplet = progress_and_pkg_trp[1].trim(); 482 | 483 | let (pkg, triplet) = match pkg_with_triplet 484 | .rsplitn(2, ':') 485 | .collect::>() 486 | .as_slice() 487 | { 488 | [t, p] => (p.to_string(), t.to_string()), 489 | _ => return None, 490 | }; 491 | 492 | let (cnt, tot) = match &progress_and_pkg_trp[0] 493 | .splitn(2, '/') 494 | .filter_map(|s| s.parse::().ok()) 495 | .collect::>() 496 | .as_slice() 497 | { 498 | [cnt, tot] => (*cnt, *tot), 499 | _ => (0, 0), 500 | }; 501 | 502 | Some((pkg, triplet, cnt, tot)) 503 | } 504 | 505 | fn run_bootstrap(vcpkg_root: &std::path::Path, verbose: bool) -> Result<(), anyhow::Error> { 506 | print_tag("Compiling", "vcpkg"); 507 | 508 | if cfg!(windows) { 509 | let mut cmd = Command::new("cmd"); 510 | cmd.arg("/C"); 511 | cmd.arg("bootstrap-vcpkg.bat"); 512 | cmd.arg("-disableMetrics"); 513 | cmd.current_dir(&vcpkg_root); 514 | run_command(cmd, verbose).context("failed to run vcpkg bootstrap")?; 515 | } else { 516 | // if we are on a mac with clang 11, try it first. Fall back to the 517 | // installation that requires gcc if this build fails 518 | if cfg!(target_os = "macos") { 519 | if let Some(version) = apple_clang_version() { 520 | if version >= 11 { 521 | let mut cmd = Command::new("sh"); 522 | cmd.arg("-c"); 523 | cmd.arg("./bootstrap-vcpkg.sh -disableMetrics -allowAppleClang"); 524 | cmd.current_dir(&vcpkg_root); 525 | if run_command(cmd, verbose).is_ok() { 526 | return Ok(()); 527 | } 528 | println!( 529 | "note: building vcpkg with apple clang failed, falling \ 530 | back to using another compiler." 531 | ); 532 | } 533 | } 534 | } 535 | 536 | let mut cmd = Command::new("sh"); 537 | cmd.arg("-c"); 538 | cmd.arg("./bootstrap-vcpkg.sh -disableMetrics"); 539 | cmd.current_dir(&vcpkg_root); 540 | run_command(cmd, verbose).context("failed to run vcpkg bootstrap")?; 541 | }; 542 | 543 | Ok(()) 544 | } 545 | 546 | fn apple_clang_version() -> Option { 547 | let output = Command::new("clang").arg("--version").output().ok()?; 548 | parse_apple_clang_version(&output.stdout) 549 | } 550 | 551 | fn parse_apple_clang_version(bytes: &[u8]) -> Option { 552 | Cursor::new(bytes) 553 | .lines() 554 | .filter_map(Result::ok) 555 | .filter(|line| line.starts_with("Apple clang version ")) 556 | .map(|line| line.trim_start_matches("Apple clang version ").to_string()) 557 | .next()? 558 | .splitn(2, '.') 559 | .next() 560 | .and_then(|x| x.parse::().ok()) 561 | } 562 | 563 | #[cfg(test)] 564 | mod test { 565 | use super::*; 566 | use std::sync::atomic::{AtomicUsize, Ordering}; 567 | use std::{ 568 | env, fs, 569 | path::{Path, PathBuf}, 570 | }; 571 | 572 | // Cadged from https://github.com/rust-lang/cargo/tree/master/crates/cargo-test-support 573 | #[derive(Default)] 574 | pub(super) struct ProjectBuilder { 575 | root: PathBuf, 576 | // files: 577 | } 578 | 579 | pub(super) fn project() -> ProjectBuilder { 580 | static NEXT_ID: AtomicUsize = AtomicUsize::new(0); 581 | let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); 582 | 583 | println!("new id {}", id); 584 | 585 | let mut root = { 586 | let mut path = env::current_exe().unwrap(); 587 | // dbg!(&path); 588 | path.pop(); // chop off exe name 589 | path.pop(); // chop off deps 590 | path.pop(); // chop off 'debug' 591 | 592 | // if path.file_name().and_then(|s| s.to_str()) != Some("target") { 593 | // path.pop(); 594 | // } 595 | 596 | path.push("cv_int"); 597 | path.mkdir_p(); 598 | path 599 | }; 600 | 601 | root.push(&format!("test_{}", id)); 602 | root.rm_rf(); 603 | root.mkdir_p(); 604 | 605 | ProjectBuilder { root } 606 | } 607 | 608 | impl ProjectBuilder { 609 | // pub(super) fn file(&mut self, name: &str, contents: &str) -> &mut Self { 610 | // self 611 | // } 612 | 613 | pub(super) fn metadata( 614 | &mut self, 615 | manifest_path: &str, 616 | ) -> Result { 617 | let mut cmd = cargo_metadata::MetadataCommand::new(); 618 | 619 | let mut path = self.root.clone(); 620 | path.push(manifest_path); 621 | cmd.manifest_path(path); 622 | 623 | Ok(cmd.exec()?) 624 | } 625 | 626 | /// Adds a file to the project. 627 | pub(super) fn file>(self, path: B, body: &str) -> Self { 628 | let path = self.root.clone().join(path); 629 | let dirname = path.parent().unwrap(); 630 | dirname.mkdir_p(); 631 | fs::write(&path, &body) 632 | .unwrap_or_else(|e| panic!("could not create file {}: {}", path.display(), e)); 633 | 634 | self 635 | } 636 | } 637 | 638 | pub trait TestPathExt { 639 | fn rm_rf(&self); 640 | fn mkdir_p(&self); 641 | } 642 | 643 | impl TestPathExt for Path { 644 | fn rm_rf(&self) { 645 | if self.exists() { 646 | if let Err(e) = remove_dir_all::remove_dir_all(self) { 647 | panic!("failed to remove {:?}: {:?}", self, e) 648 | } 649 | } 650 | } 651 | 652 | fn mkdir_p(&self) { 653 | fs::create_dir_all(self) 654 | .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e)) 655 | } 656 | } 657 | 658 | pub fn basic_manifest(name: &str, version: &str) -> String { 659 | format!( 660 | r#" 661 | [package] 662 | name = "{}" 663 | version = "{}" 664 | authors = [] 665 | "#, 666 | name, version 667 | ) 668 | } 669 | 670 | pub fn extended_manifest(name: &str, version: &str, tail: &str) -> String { 671 | format!("{}\n\n{}", &basic_manifest(name, version), tail) 672 | } 673 | 674 | #[test] 675 | fn test_parse_apple_clang_version() { 676 | assert_eq!( 677 | parse_apple_clang_version(b"la la la\nApple clang version 9.0.1"), 678 | Some(9) 679 | ); 680 | assert_eq!( 681 | parse_apple_clang_version(b"ho ho ho\nhe he he\nApple clang version 10.0.1"), 682 | Some(10) 683 | ); 684 | assert_eq!( 685 | parse_apple_clang_version(b"Apple clang version 11.0.1"), 686 | Some(11) 687 | ); 688 | assert_eq!( 689 | parse_apple_clang_version(b"Apple clang version 12.0.1"), 690 | Some(12) 691 | ); 692 | assert_eq!( 693 | parse_apple_clang_version(b"Opple clong version 12.0.1"), 694 | None 695 | ); 696 | } 697 | 698 | #[test] 699 | fn run_on_workspace_fails() { 700 | let metadata = test::project() 701 | .file( 702 | "Cargo.toml", 703 | r#" 704 | [workspace] 705 | members = ["top", "dep"] 706 | "#, 707 | ) 708 | .file( 709 | "top/Cargo.toml", 710 | &extended_manifest( 711 | "top", 712 | "0.1.0", 713 | r#" 714 | [dependencies] 715 | dep = { path = "../dep" } 716 | [package.manifest.vcpkg] 717 | dependencies = ["z85"] 718 | "#, 719 | ), 720 | ) 721 | .file("top/src/main.rs", "") 722 | .file( 723 | "dep/Cargo.toml", 724 | &extended_manifest( 725 | "dep", 726 | "0.1.0", 727 | r#" 728 | [lib] 729 | [package.manifest.vcpkg] 730 | "#, 731 | ), 732 | ) 733 | .file("dep/src/lib.rs", "") 734 | .metadata("Cargo.toml") 735 | .unwrap(); 736 | let err = process_metadata(&metadata, "").err().unwrap(); 737 | assert!(err.to_string().contains("cannot run on a virtual manifest")); 738 | } 739 | 740 | #[test] 741 | fn install_in_root_crate() { 742 | let metadata = test::project() 743 | .file( 744 | "Cargo.toml", 745 | r#" 746 | [workspace] 747 | members = ["top", "dep"] 748 | "#, 749 | ) 750 | .file( 751 | "top/Cargo.toml", 752 | &extended_manifest( 753 | "top", 754 | "0.1.0", 755 | r#" 756 | [dependencies] 757 | dep = { path = "../dep" } 758 | [package.metadata.vcpkg] 759 | install = ["z85"] 760 | "#, 761 | ), 762 | ) 763 | .file("top/src/main.rs", "") 764 | .file( 765 | "dep/Cargo.toml", 766 | &extended_manifest( 767 | "dep", 768 | "0.1.0", 769 | r#" 770 | [lib] 771 | [package.metadata.vcpkg] 772 | "#, 773 | ), 774 | ) 775 | .file("dep/src/lib.rs", "") 776 | .metadata("top/Cargo.toml") 777 | .unwrap(); 778 | 779 | let vmd = process_metadata(&metadata, "").unwrap(); 780 | assert_eq!(vmd.vcpkg_ports, vec!["z85"]); 781 | } 782 | 783 | #[test] 784 | fn same_dependencies_but_specified_triplet() { 785 | let metadata = test::project() 786 | .file( 787 | "Cargo.toml", 788 | r#" 789 | [workspace] 790 | members = ["top", "dep"] 791 | "#, 792 | ) 793 | .file( 794 | "top/Cargo.toml", 795 | &extended_manifest( 796 | "top", 797 | "0.1.0", 798 | r#" 799 | [dependencies] 800 | dep = { path = "../dep" } 801 | [package.metadata.vcpkg] 802 | install = ["z85"] 803 | [package.metadata.vcpkg.target] 804 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md" } 805 | "#, 806 | ), 807 | ) 808 | .file("top/src/main.rs", "") 809 | .file( 810 | "dep/Cargo.toml", 811 | &extended_manifest( 812 | "dep", 813 | "0.1.0", 814 | r#" 815 | [lib] 816 | [package.metadata.vcpkg] 817 | "#, 818 | ), 819 | ) 820 | .file("dep/src/lib.rs", "") 821 | .metadata("top/Cargo.toml") 822 | .unwrap(); 823 | 824 | let vmd = process_metadata(&metadata, "x86_64-pc-windows-msvc").unwrap(); 825 | assert_eq!(vmd.vcpkg_ports, vec!["z85"]); 826 | assert_eq!(vmd.vcpkg_triplet, Some("x64-windows-static-md".to_owned())); 827 | } 828 | 829 | #[test] 830 | fn same_dev_dependencies_but_specified_triplet() { 831 | let metadata = test::project() 832 | .file( 833 | "Cargo.toml", 834 | r#" 835 | [workspace] 836 | members = ["top", "dep"] 837 | "#, 838 | ) 839 | .file( 840 | "top/Cargo.toml", 841 | &extended_manifest( 842 | "top", 843 | "0.1.0", 844 | r#" 845 | [dependencies] 846 | dep = { path = "../dep" } 847 | [package.metadata.vcpkg] 848 | dependencies = ["a"] 849 | dev-dependencies = ["b"] 850 | [package.metadata.vcpkg.target] 851 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md" } 852 | "#, 853 | ), 854 | ) 855 | .file("top/src/main.rs", "") 856 | .file( 857 | "dep/Cargo.toml", 858 | &extended_manifest( 859 | "dep", 860 | "0.1.0", 861 | r#" 862 | [lib] 863 | [package.metadata.vcpkg] 864 | "#, 865 | ), 866 | ) 867 | .file("dep/src/lib.rs", "") 868 | .metadata("top/Cargo.toml") 869 | .unwrap(); 870 | 871 | let mut vmd = process_metadata(&metadata, "x86_64-pc-windows-msvc").unwrap(); 872 | vmd.vcpkg_ports.sort(); 873 | assert_eq!(vmd.vcpkg_ports, vec!["a", "b"]); 874 | assert_eq!(vmd.vcpkg_triplet, Some("x64-windows-static-md".to_owned())); 875 | } 876 | 877 | #[test] 878 | fn specified_triplet_requires_no_dependencies() { 879 | let metadata = test::project() 880 | .file( 881 | "Cargo.toml", 882 | r#" 883 | [workspace] 884 | members = ["top", "dep"] 885 | "#, 886 | ) 887 | .file( 888 | "top/Cargo.toml", 889 | &extended_manifest( 890 | "top", 891 | "0.1.0", 892 | r#" 893 | [dependencies] 894 | dep = { path = "../dep" } 895 | [package.metadata.vcpkg] 896 | install = ["z85"] 897 | [package.metadata.vcpkg.target] 898 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dependencies = [] } 899 | "#, 900 | ), 901 | ) 902 | .file("top/src/main.rs", "") 903 | .file( 904 | "dep/Cargo.toml", 905 | &extended_manifest( 906 | "dep", 907 | "0.1.0", 908 | r#" 909 | [lib] 910 | [package.metadata.vcpkg] 911 | "#, 912 | ), 913 | ) 914 | .file("dep/src/lib.rs", "") 915 | .metadata("top/Cargo.toml") 916 | .unwrap(); 917 | 918 | let vmd = process_metadata(&metadata, "x86_64-pc-windows-msvc").unwrap(); 919 | assert_eq!(vmd.vcpkg_ports, Vec::::new()); 920 | assert_eq!(vmd.vcpkg_triplet, Some("x64-windows-static-md".to_owned())); 921 | } 922 | 923 | #[test] 924 | fn combine_deps_from_all_crates() { 925 | let metadata = test::project() 926 | .file( 927 | "Cargo.toml", 928 | r#" 929 | [workspace] 930 | members = ["top", "dep"] 931 | "#, 932 | ) 933 | .file( 934 | "top/Cargo.toml", 935 | &extended_manifest( 936 | "top", 937 | "0.1.0", 938 | r#" 939 | [dependencies] 940 | dep = { path = "../dep" } 941 | [package.metadata.vcpkg] 942 | dependencies = ["a"] 943 | dev-dependencies = ["d"] 944 | [package.metadata.vcpkg.target] 945 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dev-dependencies = ["b", "c"] } 946 | "#, 947 | ), 948 | ) 949 | .file("top/src/main.rs", "") 950 | .file( 951 | "dep/Cargo.toml", 952 | &extended_manifest( 953 | "dep", 954 | "0.1.0", 955 | r#" 956 | [lib] 957 | [package.metadata.vcpkg] 958 | dependencies = ["m"] 959 | dev-dependencies = ["n"] 960 | [package.metadata.vcpkg.target] 961 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dependencies = ["o"], dev-dependencies = ["p"] } 962 | "#, 963 | ), 964 | ) 965 | .file("dep/src/lib.rs", "") 966 | .metadata("top/Cargo.toml") 967 | .unwrap(); 968 | 969 | let mut vmd = process_metadata(&metadata, "x86_64-pc-windows-msvc").unwrap(); 970 | vmd.vcpkg_ports.sort(); 971 | assert_eq!(vmd.vcpkg_ports, vec!["a", "b", "c", "o"]); 972 | assert_eq!(vmd.vcpkg_triplet, Some("x64-windows-static-md".to_owned())); 973 | 974 | let mut vmd = process_metadata(&metadata, "").unwrap(); 975 | vmd.vcpkg_ports.sort(); 976 | assert_eq!(vmd.vcpkg_ports, vec!["a", "d", "m"]); 977 | } 978 | 979 | // This test is currently disabled as it isn't clear what the desired behavior is for when 980 | // specifying vcpkg dependencies at the workspace level. This is in part due to 981 | // cargo-metadata not telling us which is the desired root crate (resolve.root == null) and 982 | // ambiguity in this case as to which git rev to use as this is usually determined by the root 983 | // crate. 984 | #[test] 985 | #[ignore] 986 | fn combine_deps_from_all_crates_and_workspace() { 987 | let metadata = test::project() 988 | .file( 989 | "Cargo.toml", 990 | r#" 991 | [workspace] 992 | members = ["top", "dep"] 993 | [workspace.metadata.vcpkg] 994 | dependencies = ["a"] 995 | dev-dependencies = ["d"] 996 | [workspace.metadata.vcpkg.target] 997 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dev-dependencies = ["b", "c"] } 998 | "#, 999 | ) 1000 | .file( 1001 | "top/Cargo.toml", 1002 | &extended_manifest( 1003 | "top", 1004 | "0.1.0", 1005 | r#" 1006 | [dependencies] 1007 | dep = { path = "../dep" } 1008 | "#, 1009 | ), 1010 | ) 1011 | .file("top/src/main.rs", "") 1012 | .file( 1013 | "dep/Cargo.toml", 1014 | &extended_manifest( 1015 | "dep", 1016 | "0.1.0", 1017 | r#" 1018 | [lib] 1019 | [package.metadata.vcpkg] 1020 | dependencies = ["m"] 1021 | dev-dependencies = ["n"] 1022 | [package.metadata.vcpkg.target] 1023 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dependencies = ["o"], dev-dependencies = ["p"] } 1024 | "#, 1025 | ), 1026 | ) 1027 | .file("dep/src/lib.rs", "") 1028 | .metadata("top/Cargo.toml") 1029 | .unwrap(); 1030 | 1031 | let mut vmd = process_metadata(&metadata, "x86_64-pc-windows-msvc").unwrap(); 1032 | vmd.vcpkg_ports.sort(); 1033 | assert_eq!(vmd.vcpkg_ports, vec!["a", "b", "c", "o"]); 1034 | assert_eq!(vmd.vcpkg_triplet, Some("x64-windows-static-md".to_owned())); 1035 | 1036 | let mut vmd = process_metadata(&metadata, "").unwrap(); 1037 | vmd.vcpkg_ports.sort(); 1038 | assert_eq!(vmd.vcpkg_ports, vec!["a", "d", "m"]); 1039 | } 1040 | } 1041 | -------------------------------------------------------------------------------- /wstest/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.x86_64-pc-windows-msvc] 2 | rustflags = ["-Ctarget-feature=+crt-static"] 3 | -------------------------------------------------------------------------------- /wstest/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "foo" 5 | version = "0.1.0" 6 | 7 | [[package]] 8 | name = "vcpkg" 9 | version = "0.2.9" 10 | source = "registry+https://github.com/rust-lang/crates.io-index" 11 | checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c" 12 | 13 | [[package]] 14 | name = "wstest" 15 | version = "0.1.0" 16 | dependencies = [ 17 | "foo", 18 | "vcpkg", 19 | ] 20 | -------------------------------------------------------------------------------- /wstest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ "wstest" ] 3 | 4 | #[patch.crates-io] 5 | #vcpkg = { path = '../vcpkg' } 6 | 7 | # [patch.'https://github.com/mcgoo/vcpkg-rs'] 8 | # vcpkg = { path = 'vcpkg' } 9 | -------------------------------------------------------------------------------- /wstest/foo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "foo" 3 | version = "0.1.0" 4 | authors = ["Jim McGrath "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | [package.metadata.vcpkg] 12 | install = ["z85"] 13 | -------------------------------------------------------------------------------- /wstest/foo/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /wstest/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | cd $SCRIPTDIR 6 | 7 | unset VCPKG_ROOT 8 | unset RUSTFLAGS 9 | unset VCPKGRS_DYNAMIC 10 | 11 | pushd .. 12 | cargo install --path . 13 | popd 14 | 15 | cargo vcpkg build --manifest-path=wstest/Cargo.toml 16 | cargo run --manifest-path=wstest/Cargo.toml 17 | -------------------------------------------------------------------------------- /wstest/wstest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wstest" 3 | version = "0.1.0" 4 | authors = ["Jim McGrath "] 5 | edition = "2018" 6 | 7 | [build-dependencies] 8 | vcpkg = { version = "0.2.9" } 9 | 10 | [dependencies] 11 | foo = { path = "../foo" } 12 | 13 | [package.metadata.vcpkg] 14 | git = "https://github.com/microsoft/vcpkg" 15 | rev = "4c1db68" 16 | #branch = "master" 17 | #tag = "2020.04" 18 | 19 | [package.metadata.vcpkg.target] 20 | x86_64-apple-darwin = { install = ["sdl2"] } 21 | x86_64-unknown-linux-gnu = { install = ["sdl2"] } 22 | x86_64-pc-windows-msvc = { triplet = "x64-windows-static", install = ["sdl2"] } 23 | -------------------------------------------------------------------------------- /wstest/wstest/README.md: -------------------------------------------------------------------------------- 1 | # Workspace test 2 | 3 | This is a test for putting the vcpkg configuration into Cargo.toml. 4 | -------------------------------------------------------------------------------- /wstest/wstest/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!( 3 | "RUSTFLAGS={}", 4 | std::env::var("RUSTFLAGS").unwrap_or_default() 5 | ); 6 | // panic!("CARGO={}", std::env::var("CARGO").unwrap()); 7 | vcpkg::find_package("sdl2").unwrap(); 8 | } 9 | -------------------------------------------------------------------------------- /wstest/wstest/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | --------------------------------------------------------------------------------