summary refs log tree commit diff
path: root/pkgs/build-support/rust/build-rust-crate/lib.sh
blob: 5843ee98b0d56f7c195a4330f9cd518121f8e750 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
echo_build_heading() {
  if (( $# == 1 )); then
    echo_colored "Building $1"
  else
    echo_colored "Building $1 ($2)"
  fi
}

build_lib() {
  lib_src=$1
  echo_build_heading $lib_src ${libName}

  noisily rustc \
    --crate-name $CRATE_NAME \
    $lib_src \
    --out-dir target/lib \
    --emit=dep-info,link \
    -L dependency=target/deps \
    --cap-lints allow \
    $LIB_RUSTC_OPTS \
    $BUILD_OUT_DIR \
    $EXTRA_BUILD \
    $EXTRA_FEATURES \
    $EXTRA_RUSTC_FLAGS \
    --color $colors

  EXTRA_LIB=" --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-$metadata.rlib"
  if [ -e target/deps/lib$CRATE_NAME-$metadata$LIB_EXT ]; then
     EXTRA_LIB="$EXTRA_LIB --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-$metadata$LIB_EXT"
  fi
}

build_bin() {
  local crate_name=$1
  local crate_name_=$(echo $crate_name | tr '-' '_')
  local main_file=""

  if [[ ! -z $2 ]]; then
    main_file=$2
  fi
  echo_build_heading $@
  noisily rustc \
    --crate-name $crate_name_ \
    $main_file \
    --crate-type bin \
    $BIN_RUSTC_OPTS \
    --out-dir target/bin \
    --emit=dep-info,link \
    -L dependency=target/deps \
    $LINK \
    $EXTRA_LIB \
    --cap-lints allow \
    $BUILD_OUT_DIR \
    $EXTRA_BUILD \
    $EXTRA_FEATURES \
    $EXTRA_RUSTC_FLAGS \
    --color ${colors} \

  if [ "$crate_name_" != "$crate_name" ]; then
    mv target/bin/$crate_name_ target/bin/$crate_name
  fi
}

build_lib_test() {
    local file="$1"
    EXTRA_RUSTC_FLAGS="--test $EXTRA_RUSTC_FLAGS" build_lib "$1" "$2"
}

build_bin_test() {
    local crate="$1"
    local file="$2"
    EXTRA_RUSTC_FLAGS="--test $EXTRA_RUSTC_FLAGS" build_bin "$1" "$2"
}

build_bin_test_file() {
    local file="$1"
    local derived_crate_name="${file//\//_}"
    derived_crate_name="${derived_crate_name%.rs}"
    build_bin_test "$derived_crate_name" "$file"
}

# Add additional link options that were provided by the build script.
setup_link_paths() {
  EXTRA_LIB=""
  if [[ -e target/link_ ]]; then
    EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD"
  fi

  echo "$EXTRA_LINK_SEARCH" | while read i; do
     if [[ ! -z "$i" ]]; then
       for library in $i; do
         echo "-L $library" >> target/link
         L=$(echo $library | sed -e "s#$(pwd)/target/build#$lib/lib#")
         echo "-L $L" >> target/link.final
       done
     fi
  done
  echo "$EXTRA_LINK" | while read i; do
     if [[ ! -z "$i" ]]; then
       for library in $i; do
         echo "-l $library" >> target/link
         echo "-l $library" >> target/link.final
       done
     fi
  done

  if [[ -e target/link ]]; then
     sort -u target/link.final > target/link.final.sorted
     mv target/link.final.sorted target/link.final
     sort -u target/link > target/link.sorted
     mv target/link.sorted target/link

     tr '\n' ' ' < target/link > target/link_
     LINK=$(cat target/link_)
  fi
}

search_for_bin_path() {
  # heuristic to "guess" the correct source file as found in cargo:
  # https://github.com/rust-lang/cargo/blob/90fc9f620190d5fa3c80b0c8c65a1e1361e6b8ae/src/cargo/util/toml/targets.rs#L308-L325

  BIN_NAME=$1
  BIN_NAME_=$(echo $BIN_NAME | tr '-' '_')

  # the first two cases are the "new" default IIRC
  FILES=( "src/bin/$BIN_NAME.rs" "src/bin/$BIN_NAME/main.rs" "src/bin/$BIN_NAME_.rs" "src/bin/$BIN_NAME_/main.rs" "src/bin/main.rs" "src/main.rs" )

  if ! [ -e "$LIB_PATH" -o -e src/lib.rs -o -e "src/$LIB_NAME.rs" ]; then
    # if this is not a library the following path is also valid
    FILES=( "src/$BIN_NAME.rs" "src/$BIN_NAME_.rs" "${FILES[@]}" )
  fi

  for file in "${FILES[@]}";
  do
    echo "checking file $file"
    # first file that exists wins
    if [[ -e "$file" ]]; then
            BIN_PATH="$file"
            break
    fi
  done

  if [[ -z "$BIN_PATH" ]]; then
    echo_error "ERROR: failed to find file for binary target: $BIN_NAME" >&2
    exit 1
  fi
}

# Extracts cargo_toml_path of the matching crate.
matching_cargo_toml_path() {
  local manifest_path="$1"
  local expected_crate_name="$2"

  # If the Cargo.toml is not a workspace root,
  # it will only contain one package in ".packages"
  # because "--no-deps" suppressed dependency resolution.
  #
  # But to make it more general, we search for a matching
  # crate in all packages and use the manifest path that
  # is referenced there.
  cargo metadata --no-deps --format-version 1 \
    --manifest-path "$manifest_path" \
    | jq -r '.packages[] 
            | select( .name == "'$expected_crate_name'") 
            | .manifest_path'
}

# Find a Cargo.toml in the current or any sub directory
# with a matching crate name.
matching_cargo_toml_dir() {
  local expected_crate_name="$1"

  find -L -name Cargo.toml | sort | while read manifest_path; do
    echo "...checking manifest_path $manifest_path" >&2
    local matching_path="$(matching_cargo_toml_path "$manifest_path" "$expected_crate_name")"
    if [ -n "${matching_path}" ]; then
      echo "$(dirname $matching_path)"
      break
    fi
  done
}