1 Star 0 Fork 129

xuhf / xmake

forked from tboox / xmake 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
configure 126.56 KB
一键复制 编辑 原始数据 按行查看 历史
ruki 提交于 2023-06-28 00:36 . revert soname
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212
#!/bin/sh
# A script-only build utility like autotools
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http:##www.apache.org#licenses#LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright (C) 2022-present, TBOOX Open Source Group.
#
# @author ruki
# @homepage https://github.com/xmake-io/xmake.sh
#
#-----------------------------------------------------------------------------
# some constants
#
xmake_sh_projectdir=$(X= cd -- "$(dirname -- "$0")" && pwd -P)
xmake_sh_buildir="build"
xmake_sh_version="1.0.5"
xmake_sh_verbose=false
xmake_sh_diagnosis=false
xmake_sh_copyright="Copyright (C) 2022-present Ruki Wang, tboox.org, xmake.io."
xmake_sh_makefile="${xmake_sh_projectdir}/makefile"
#-----------------------------------------------------------------------------
# some helper functions
#
raise() {
echo "$@" 1>&2 ; exit 1
}
vprint() {
if "${xmake_sh_verbose}"; then
echo "$@"
fi
}
dprint() {
if "${xmake_sh_diagnosis}"; then
echo "$@"
fi
}
# show and escape string instead of `echo -e`, because sh does not support it
print() {
printf "${@}\n"
}
wprint() {
if "${xmake_sh_verbose}"; then
printf "warning: ${@}\n"
fi
}
# test empty string
test_z() {
if test "x${1}" = "x"; then
return 0
fi
return 1
}
# test non-empty string
test_nz() {
if test "x${1}" != "x"; then
return 0
fi
return 1
}
# test string is equal
test_eq() {
if test "x${1}" = "x${2}"; then
return 0
fi
return 1
}
# test string is not equal
test_nq() {
if test "x${1}" != "x${2}"; then
return 0
fi
return 1
}
string_toupper() {
_ret=$(echo "$1" | tr '[a-z]' '[A-Z]')
}
string_tolower() {
_ret=$(echo "$1" | tr '[A-Z]' '[a-z]')
}
string_replace() {
_ret=$(echo "$1" | sed "s/${2}/${3}/g")
}
# we avoid use `cut` command, because it's slow
string_split() {
local str="${1}"
local sep="${2}"
local idx="${3}"
local oldifs="${IFS}"
IFS="${sep}"
set -- ${str}
if test_nz "${idx}"; then
case "${idx}" in
1) _ret="$1";;
2) _ret="$2";;
3) _ret="$3";;
4) _ret="$4";;
5) _ret="$5";;
6) _ret="$6";;
esac
else
_ret="$1"
_ret2="$2"
_ret3="$3"
_ret4="$4"
_ret5="$5"
_ret6="$6"
fi
IFS="${oldifs}"
}
# does contain sub-string?
# e.g.
# str="src/*.cpp"
# string_contains "$str" "src"
string_contains() {
case "${1}" in
*${2}*) return 0;;
*) return 1;;
esac
return 1
}
# does contain "*"?
string_contains_star() {
case "${1}" in
*\**) return 0;; # bash
*'*'*) return 0;; # csh
*) return 1;;
esac
return 1
}
# does contain "**"?
string_contains_star2() {
case "${1}" in
*\*\**) return 0;; # bash
*'**'*) return 0;; # csh
*) return 1;;
esac
return 1
}
# does startswith sub-string?
# e.g.
# str="src/*.cpp"
# string_startswith "$str" "src"
string_startswith() {
case "${1}" in
${2}*) return 0;;
*) return 1;;
esac
return 1
}
# duplicate characters
# e.g. string_dupch 10 "." => ...........
string_dupch() {
local count=${1}
local ch=${2}
printf %${count}s | tr " " "${ch}"
}
# replace file content
_io_replace_file() {
local infile="${1}"
local outfile="${2}"
local patterns="${3}"
sed "/./ {${patterns}}" "${infile}" > "${outfile}"
}
# try remove file or directory
_os_tryrm() {
if test -f "${1}"; then
rm "${1}"
elif test -d "${1}"; then
rm -r "${1}"
fi
}
# get temporary file
_os_tmpfile() {
_ret=$(mktemp)
}
# try run program
_os_runv() {
if ${xmake_sh_diagnosis}; then
${@}
else
${@} >/dev/null 2>&1
fi
local ok=$?
if test "${ok}" -ne "0"; then
return 1
fi
return 0
}
# try run program and get output
_os_iorunv() {
_os_tmpfile
local tmpfile="${_ret}"
${@} >"${tmpfile}" 2>&1
local ok=$?
if test "${ok}" -ne "0"; then
_ret=""
else
local result=$(cat "${tmpfile}")
_ret="${result}"
fi
_os_tryrm "${tmpfile}"
}
# find file in the given directory
# e.g. _os_find . xmake.sh
_os_find() {
local dir="${1}"
local name="${2}"
local depth="${3}"
if test_nz "${depth}"; then
if is_host "macosx"; then
_ret=$(find "${dir}" -depth "${depth}" -type f -name "${name}")
else
_ret=$(find "${dir}" -maxdepth "${depth}" -mindepth "${depth}" -type f -name "${name}")
fi
else
_ret=$(find "${dir}" -type f -name "${name}")
fi
}
# get date, "%Y%m%d%H%M" -> 202212072222
_os_date() {
_ret=$(date +"${1}")
}
# we avoid use `basename`, because it's slow
path_filename() {
local path="${1}"
if test_eq "${path}" "/"; then
_ret="/"
else
_ret="${path##*/}"
fi
}
path_extension() {
path_filename "${1}"; local filename="${_ret}"
_ret=".${filename##*.}"
}
path_basename() {
path_filename "${1}"; local filename="${_ret}"
_ret="${filename%.*}"
}
# we avoid use `dirname -- ${1}`, because it's too slow
path_directory() {
local path="${1}"
if test_z "${path}"; then
raise "invalid empty path in path_directory()."
fi
path="${path%/}"
local dir="${path%/*}"
if string_startswith "${path}" "/"; then
if test_z "${dir}"; then
dir="/"
fi
else
dir="${dir#/}"
if test_z "${dir}"; then
dir="."
fi
fi
_ret="${dir}"
}
# e.g. path_filename_fromdir "/tmp/file" "/tmp" -> "file"
path_filename_fromdir() {
_ret="${1#${2}/}"
}
path_is_absolute() {
if string_startswith "${1}" "/"; then
return 0
fi
return 1
}
# get relative path, e.g $(path_relative ${rootdir} ${absolute_path}`
path_relative() {
local source="${1}"
local target="${2}"
if test_z "${source}" || test_z "${target}"; then
raise "invalid empty path in path_relative()"
fi
# patch missing "./"
source=${source#./}
source=${source#.}
target=${target#./}
target=${target#.}
if test_z "${source}"; then
_ret="${target}"
return
fi
# find common path
local result=""
local common_part=$source
while test_eq "${target#$common_part}" "${target}"; do
# no match, means that candidate common part is not correct
# go up one level (reduce common part)
path_directory "${common_part}"; common_part="${_ret}"
# and record that we went back, with correct / handling
if test_z "${result}"; then
result=".."
else
result="../${result}"
fi
done
if test_eq "${common_part}" "/"; then
# special case for root (no common path)
result="${result}/"
fi
# since we now have identified the common part,
# compute the non-common part
local forward_part="${target#$common_part}"
# and now stick all parts together
if test_nz "${result}" && test_nz "${forward_part}"; then
result="${result}${forward_part}"
elif test_nz "${forward_part}"; then
result="${forward_part#*/}"
fi
# same directory?
if test_z "${result}" && test_eq "${source}" "${target}"; then
result="."
fi
_ret="${result}"
}
path_sourcekind() {
local sourcekind=""
case "${1}" in
*.cpp) sourcekind="cxx";;
*.cc) sourcekind="cxx";;
*.c) sourcekind="cc";;
*.ixx) sourcekind="cxx";;
*.mm) sourcekind="mxx";;
*.m) sourcekind="mm";;
*.S) sourcekind="as";;
*.s) sourcekind="as";;
*.asm) sourcekind="as";;
*) raise "unknown sourcekind for ${1}" ;;
esac
_ret="${sourcekind}"
}
path_toolname() {
local toolname=""
case "${1}" in
*-gcc) toolname="gcc";;
*/gcc) toolname="gcc";;
gcc) toolname="gcc";;
gcc-*) toolname="gcc";;
*/gcc-*) toolname="gcc";;
*-g++) toolname="gxx";;
*/g++) toolname="gxx";;
g++) toolname="gxx";;
g++-*) toolname="gxx";;
*/g++-*) toolname="gxx";;
xcrun*clang++) toolname="clangxx";;
xcrun*clang) toolname="clang";;
*-clang++) toolname="clangxx";;
*/clang++) toolname="clangxx";;
clang++) toolname="clangxx";;
clang++-*) toolname="clangxx";;
*/clang++-*) toolname="clangxx";;
*-clang) toolname="clang";;
*/clang) toolname="clang";;
clang) toolname="clang";;
clang-*) toolname="clang";;
*/clang-*) toolname="clang";;
*/emcc) toolname="emcc";;
emcc) toolname="emcc";;
*/em++) toolname="emxx";;
em++) toolname="emxx";;
*-ar) toolname="ar";;
*/ar) toolname="ar";;
ar) toolname="ar";;
*/emar) toolname="emar";;
emar) toolname="emar";;
cc) toolname="gcc";;
*/cc) toolname="gcc";;
c++) toolname="gxx";;
*/c++) toolname="gxx";;
*) raise "unknown tool ${1}";;
esac
_ret="${toolname}"
}
# get flag name from toolkind, e.g. cc => cflags, cxx => cxxflags
_get_flagname() {
local toolkind="${1}"
local flagname=""
case "${toolkind}" in
cc) flagname="cflags";;
cxx) flagname="cxxflags";;
as) flagname="asflags";;
mm) flagname="mflags";;
mxx) flagname="mxxflags";;
ar) flagname="arflags";;
sh) flagname="shflags";;
ld) flagname="ldflags";;
*) raise "unknown toolkind(${toolkind})!" ;;
esac
_ret="${flagname}"
}
# is enabled? true, yes, y
_is_enabled() {
local value=${1}
if test_eq "${value}" "true"; then
return 0
elif test_eq "${value}" "yes"; then
return 0
elif test_eq "${value}" "y"; then
return 0
fi
return 1
}
# deduplicate string list
# .e.g "hello world hello how are you world" -> hello world how are you
_dedup() {
_ret=$(echo "${1}" | awk '{for (i = 1; i <= NF; ++i) if (!seen[$i]++) printf $i " "}')
}
# deduplicate string list from the reverse order
# .e.g "hello world hello how are you world" -> hello how are you world
_dedup_reverse() {
local result=""
local list=""
local item=""
list=$(echo "${1}" | awk '{for (i = NF; i > 0; --i) if (!seen[$i]++) printf $i " "}')
for item in ${list}; do
result="${item} ${result}"
done
_ret="${result}"
}
#-----------------------------------------------------------------------------
# map functions
#
# define map, @note we can not use bash/declare to define map, because sh does not support it.
#
# _map "options"
# _map_set "options" "key1" "value1"
# _map_set "options" "key2" "value2"
# _map_set "options" "key2" "value3"
# _map_set "options" "key3" "value3"
# _map_set "options" "key4" "__empty__"
# _map_set "options" "key4" "__empty__"
# _map_count "options"; _count="${_ret}"
# _map_keys "options"; _keys="${_ret}"
# echo ${_count}
# for key in ${_keys}; do
# _map_get "options" ${key}; value="{_ret}"
# echo ${key} "->" ${value}
# done
#
# echo "------"
# _map_remove "options" "key3"
# _map_count "options"; _count="${_ret}"
# _map_keys "options"; _keys="${_ret}"
# echo ${_count}
# for key in ${_keys}; do
# _map_get "options" ${key}; value="{_ret}"
# echo ${key} "->" ${value}
# done
#
_map() {
local name=${1}
# eval _map_${name}_count=0
# eval _map_${name}_keys=""
}
# because the shell is slow, we have to temporarily
# disable some of the map features for performance.
#
#_map_count() {
# local name=${1}
# local count=$(eval echo \$_map_${name}_count)
# _ret="${count}"
#}
_map_get() {
local name="${1}"
local key="${2}"
_ret=$(eval echo \$_map_${name}_value_${key})
if test_eq "${_ret}" "__empty__"; then
_ret=""
fi
}
_map_has() {
local name="${1}"
local key="${2}"
local value=""
value=$(eval echo \$_map_${name}_value_${key})
if test_nz "${value}"; then
return 0
fi
return 1
}
_map_set() {
local name="${1}"
local key="${2}"
local value="${3}"
# if ! _map_has ${name} ${key}; then
# _map_count "options"; local count="${_ret}"
# eval _map_${name}_count=$((${count} + 1))
# local keys=$(eval echo \$_map_${name}_keys)
# keys="${keys} ${key}"
# eval _map_${name}_keys=\${keys}
# fi
eval _map_${name}_value_${key}=\${value}
}
#_map_remove() {
# local name="${1}"
# local key="${2}"
# if _map_has ${name} ${key}; then
# _map_count "options"; local count="${_ret}"
# eval _map_${name}_count=$((${count} - 1))
# eval _map_${name}_value_${key}=""
# local keys=$(eval echo \$_map_${name}_keys)
# local keys_new=""
# local k=""
# for k in ${keys}; do
# if test_nq "${k}" "${key}"; then
# keys_new="${keys_new} ${k}"
# fi
# done
# eval _map_${name}_keys=\${keys_new}
# fi
#}
#_map_keys() {
# local name="${1}"
# local keys=$(eval echo \$_map_${name}_keys)
# _ret="${keys}"
#}
#-----------------------------------------------------------------------------
# detect default environments
#
# detect hosts
os_host=`uname`
string_tolower ${os_host}; os_host="${_ret}"
if echo "${os_host}" | grep cygwin >/dev/null 2>&1; then
os_host="cygwin"
fi
if echo "${os_host}" | grep msys >/dev/null 2>&1; then
os_host="msys"
fi
if echo "${os_host}" | grep mingw >/dev/null 2>&1; then
os_host="msys"
fi
if echo "${os_host}" | grep darwin >/dev/null 2>&1; then
os_host="macosx"
fi
if echo "${os_host}" | grep linux >/dev/null 2>&1; then
os_host="linux"
fi
if echo "${os_host}" | grep freebsd >/dev/null 2>&1; then
os_host="freebsd"
fi
if echo "${os_host}" | grep bsd >/dev/null 2>&1; then
os_host="bsd"
fi
if echo "${os_host}" | grep Haiku >/dev/null 2>&1; then
os_host="haiku"
fi
# determining host
# e.g.
# if is_host "linux" "macosx"; then
# ...
# fi
is_host() {
local host=""
for host in $@; do
if test_eq "${os_host}" "${host}"; then
return 0
fi
done
return 1
}
# detect host architecture
os_arch=`uname -m | tr '[A-Z]' '[a-z]'`
if test_eq "${os_arch}" "i686"; then
os_arch="i386"
elif test_eq "${os_arch}" "aarch64"; then
os_arch="arm64"
elif string_contains "${os_arch}" "armv7"; then
os_arch="armv7"
fi
# set the default target platform
_target_plat_default=${os_host}
if is_host "msys"; then
_target_plat_default="mingw"
elif is_host "freebsd"; then
_target_plat_default="bsd"
elif test_nz "${EMSDK}"; then
_target_plat_default="wasm"
fi
# set the default target architecture
_target_arch_default=${os_arch}
if is_host "msys" && test_nz "${MSYSTEM_CARCH}"; then
_target_arch_default="${MSYSTEM_CARCH}"
elif test_nz "${TERMUX_ARCH}"; then
_target_arch_default="${TERMUX_ARCH}"
elif test_nz "${EMSDK}"; then
_target_arch_default="wasm32"
fi
if test_eq "${_target_arch_default}" "i686"; then
_target_arch_default="i386"
elif test_eq "${_target_arch_default}" "aarch64"; then
_target_arch_default="arm64"
elif string_contains "${_target_arch_default}" "armv7"; then
_target_arch_default="armv7"
fi
# set the default target mode
_target_mode_default="release"
# set the default target kind
_target_kind_default="static"
# set the default project generator and build program
if is_host "freebsd" "bsd"; then
_project_generator="gmake"
_make_program_default="gmake"
_ninja_program_default="ninja"
elif is_host "msys" "cygwin"; then
_project_generator="gmake"
_make_program_default="make.exe"
_ninja_program_default="ninja.exe"
else
_project_generator="gmake"
_make_program_default="make"
_ninja_program_default="ninja"
fi
# set the default directories
if test -d "/usr/local"; then
_install_prefix_default="/usr/local"
elif test -d "/usr"; then
_install_prefix_default="/usr"
fi
_install_bindir_default="\${prefix}/bin"
_install_libdir_default="\${prefix}/lib"
_install_includedir_default="\${prefix}/include"
# determining target platform
# e.g.
# if is_plat "linux" "macosx"; then
# ...
# fi
is_plat() {
local plat=""
for plat in $@; do
if test_eq "${_target_plat}" "${plat}"; then
return 0
fi
done
return 1
}
# determining target architecture
# e.g.
# if is_arch "x86_64" "i386"; then
# ...
# fi
is_arch() {
local arch=""
for arch in $@; do
if test_eq "${_target_arch}" "${arch}"; then
return 0
fi
done
return 1
}
# determining target mode
# e.g.
# if is_mode "release"; then
# ...
# fi
is_mode() {
local mode=""
for mode in $@; do
if test_eq "${_target_mode}" "${mode}"; then
return 0
fi
done
return 1
}
# determining target kind
# e.g.
# if is_kind "release"; then
# ...
# fi
is_kind() {
local kind=""
for kind in $@; do
if test_eq "${_target_kind}" "${kind}"; then
return 0
fi
done
return 1
}
# determining target toolchain
# e.g.
# if is_toolchain "clang"; then
# ...
# fi
is_toolchain() {
local toolchain=""
for toolchain in $@; do
if test_eq "${_target_toolchain}" "${toolchain}"; then
return 0
fi
done
return 1
}
#-----------------------------------------------------------------------------
# project configuration apis
#
# set project name
set_project() {
_xmake_sh_project_name="${1}"
}
# include the given xmake.sh file or directory
# e.g. includes "src" "tests"
includes() {
local path=""
for path in $@; do
if test -f "${path}"; then
path_directory "${path}"; xmake_sh_scriptdir="${_ret}"
. "${path}"
else
local xmake_sh_scriptdir_cur=${xmake_sh_scriptdir}
if test "x${xmake_sh_scriptdir}" != "x"; then
xmake_sh_scriptdir="${xmake_sh_scriptdir_cur}/${path}"
. "${xmake_sh_scriptdir}/xmake.sh"
else
. "${xmake_sh_projectdir}/${path}/xmake.sh"
fi
xmake_sh_scriptdir=${xmake_sh_scriptdir_cur}
fi
done
}
#-----------------------------------------------------------------------------
# some helper functions
#
# split flags
_split_flags() {
string_replace "${1}" ":" " "
}
# get abstract flag for gcc/clang
_get_abstract_flag_for_gcc_clang() {
local toolkind="${1}"
local toolname="${2}"
local itemname="${3}"
local value="${4}"
local flag=""
case "${itemname}" in
defines)
string_replace "${value}" '"' '\\\"'; value="${_ret}"
flag="-D${value}"
;;
undefines) flag="-U${value}";;
includedirs) flag="-I${value}";;
linkdirs) flag="-L${value}";;
links) flag="-l${value}";;
syslinks) flag="-l${value}";;
frameworks) flag="-framework ${value}";;
frameworkdirs) flag="-F${value}";;
rpathdirs)
if is_plat "macosx"; then
string_replace "${value}" "\$ORIGIN" "@loader_path"; value="${_ret}"
flag="-Xlinker -rpath -Xlinker ${value}"
else
# escape $ORIGIN in makefile, TODO we need also handle it for ninja
string_replace "${value}" "@loader_path" '$$ORIGIN'; value="${_ret}"
if is_plat "bsd"; then
flag="-Wl,-zorigin -Wl,-rpath='${value}'"
else
flag="-Wl,-rpath='${value}'"
fi
fi
;;
symbols)
if test_eq "${value}" "debug"; then
flag="-g"
elif test_eq "${value}" "hidden"; then
flag="-fvisibility=hidden"
fi
;;
strip)
if test_eq "${value}" "debug"; then
flag="-Wl,-S"
elif test_eq "${value}" "all"; then
if is_plat "macosx"; then
flag="-Wl,-x -Wl,-dead_strip"
else
flag="-s"
fi
fi
;;
warnings)
if test_eq "${value}" "all" || test_eq "${value}" "more" || test_eq "${value}" "less"; then
flag="-Wall"
elif test_eq "${value}" "allextra"; then
flag="-Wall -Wextra"
elif test_eq "${value}" "error"; then
flag="-Werror"
elif test_eq "${value}" "everything"; then
flag="-Wall -Wextra"
elif test_eq "${value}" "none"; then
flag="-w"
fi
;;
optimizes)
if test_eq "${value}" "fast"; then
flag="-O1"
elif test_eq "${value}" "faster"; then
flag="-O2"
elif test_eq "${value}" "fastest"; then
flag="-O3"
elif test_eq "${value}" "smallest"; then
if test_eq "${toolname}" "clang" || test_eq "${toolname}" "clangxx"; then
flag="-Oz"
else
flag="-Os"
fi
elif test_eq "${value}" "aggressive"; then
flag="-Ofast"
elif test_eq "${value}" "none"; then
flag="-O0"
fi
;;
languages)
if test_eq "${toolkind}" "cc" || test_eq "${toolkind}" "mm"; then
case "${value}" in
ansi) flag="-ansi";;
c89) flag="-std=c89";;
gnu89) flag="-std=gnu89";;
c99) flag="-std=c99";;
gnu99) flag="-std=gnu99";;
c11) flag="-std=c11";;
gnu11) flag="-std=gnu11";;
c17) flag="-std=c17";;
gnu17) flag="-std=gnu17";;
esac
elif test_eq "${toolkind}" "cxx" || test_eq "${toolkind}" "mxx"; then
case "${value}" in
cxx98) flag="-std=c++98";;
c++98) flag="-std=c++98";;
gnuxx98) flag="-std=gnu++98";;
gnu++98) flag="-std=gnu++98";;
cxx11) flag="-std=c++11";;
c++11) flag="-std=c++11";;
gnuxx11) flag="-std=gnu++11";;
gnu++11) flag="-std=gnu++11";;
cxx14) flag="-std=c++14";;
c++14) flag="-std=c++14";;
gnuxx14) flag="-std=gnu++14";;
gnu++14) flag="-std=gnu++14";;
cxx17) flag="-std=c++17";;
c++17) flag="-std=c++17";;
gnuxx17) flag="-std=gnu++17";;
gnu++17) flag="-std=gnu++17";;
cxx1z) flag="-std=c++1z";;
c++1z) flag="-std=c++1z";;
gnuxx1z) flag="-std=gnu++1z";;
gnu++1z) flag="-std=gnu++1z";;
cxx2a) flag="-std=c++2a";;
c++2a) flag="-std=c++2a";;
gnuxx2a) flag="-std=gnu++2a";;
gnu++2a) flag="-std=gnu++2a";;
cxx20) flag="-std=c++20";;
c++20) flag="-std=c++20";;
gnuxx20) flag="-std=gnu++20";;
gnu++20) flag="-std=gnu++20";;
cxx*) raise "unknown language value(${value})!" ;;
c++*) raise "unknown language value(${value})!" ;;
esac
fi
;;
*) raise "unknown itemname(${itemname})!" ;;
esac
_ret="${flag}"
}
# get abstract flags
_get_abstract_flags() {
local toolkind="${1}"
local toolname="${2}"
local itemname="${3}"
local values="${4}"
local flags=""
local value=""
for value in ${values}; do
local flag=""
case "${toolname}" in
gcc) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
gxx) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
clang) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
clangxx) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
emcc) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
emxx) _get_abstract_flag_for_gcc_clang "${toolkind}" "${toolname}" "${itemname}" "${value}"; flag="${_ret}";;
*) raise "unknown toolname(${toolname})!" ;;
esac
if test_nz "${flag}"; then
flags="${flags} ${flag}"
fi
done
_ret="${flags}"
}
#-----------------------------------------------------------------------------
# option configuration apis
#
# define option
option() {
local name="${1}"
local description="${2}"
local default=${3}
_xmake_sh_option_current="${name}"
if ! ${_loading_options}; then
if test_nz "${description}"; then
_xmake_sh_option_current=""
fi
return
fi
if ! _map_has "options" "${name}_name"; then
_xmake_sh_options="${_xmake_sh_options} ${name}"
fi
_map_set "options" "${name}_name" "${name}"
_map_set "options" "${name}_description" "${description}"
_map_set "options" "${name}_default" "${default}"
# we end option if it's just one line
if test_nz "${description}"; then
_xmake_sh_option_current=""
fi
return 0
}
option_end() {
_xmake_sh_option_current=""
}
_map "options"
# has the given option?
_has_option() {
local name=${1}
if _map_has "options" "${name}_name"; then
return 0
fi
return 1
}
# get the given option item
_get_option_item() {
local name=${1}
local key=${2}
_map_get "options" "${name}_${key}"
}
# set the given option item
_set_option_item() {
local name=${1}
local key=${2}
shift
shift
if test_nz "${name}"; then
_map_set "options" "${name}_${key}" "${@}"
else
raise "please call set_${key}(${@}) in the option scope!"
fi
}
# add values to the given option item
_add_option_item() {
local name=${1}
local key=${2}
shift
shift
if test_nz "${name}"; then
_map_get "options" "${name}_${key}"; local values="${_ret}"
values="${values} ${@}"
_map_set "options" "${name}_${key}" "${values}"
else
raise "please call add_${key}(${@}) in the option scope!"
fi
}
# get the give option value
_get_option_value() {
local name=${1}
_get_option_item "${name}" "value"
if test "x${_ret}" = "x"; then
_get_option_item "${name}" "default"
fi
}
# set the give option value
_set_option_value() {
local name=${1}
local value=${2}
_set_option_item "${name}" "value" "${value}"
}
# this option need checking?
_option_need_checking() {
local name="${1}"
_get_option_item "${name}" "default"; local default="${_ret}"
if test_nz "${default}"; then
return 1
fi
_get_option_item "${name}" "cfuncs"; local cfuncs="${_ret}"
_get_option_item "${name}" "cxxfuncs"; local cxxfuncs="${_ret}"
_get_option_item "${name}" "cincludes"; local cincludes="${_ret}"
_get_option_item "${name}" "cxxincludes"; local cxxincludes="${_ret}"
_get_option_item "${name}" "ctypes"; local ctypes="${_ret}"
_get_option_item "${name}" "cxxtypes"; local cxxtypes="${_ret}"
_get_option_item "${name}" "csnippets"; local csnippets="${_ret}"
_get_option_item "${name}" "cxxsnippets"; local cxxsnippets="${_ret}"
_get_option_item "${name}" "links"; local links="${_ret}"
_get_option_item "${name}" "syslinks"; local syslinks="${_ret}"
if test_nz "${cfuncs}" || test_nz "${cxxfuncs}" ||
test_nz "${cincludes}" || test_nz "${cxxincludes}" ||
test_nz "${ctypes}" || test_nz "${cxxtypes}" ||
test_nz "${csnippets}" || test_nz "${cxxsnippets}" ||
test_nz "${links}" || test_nz "${syslinks}"; then
return 0
fi
return 1
}
# get options for the help menu
_get_options_for_menu() {
local options=""
local name=""
for name in ${_xmake_sh_options}; do
_get_option_item "${name}" "showmenu"; local showmenu="${_ret}"
if _is_enabled "${showmenu}"; then
options="${options} ${name}"
elif test_z "${showmenu}" && ! _option_need_checking "${name}"; then
options="${options} ${name}"
fi
done
_ret="${options}"
}
# get options for checking
_get_options_for_checking() {
local options=""
local name=""
for name in ${_xmake_sh_options}; do
_get_option_item "${name}" "showmenu"; local showmenu="${_ret}"
if test_z "${showmenu}" && _option_need_checking "${name}"; then
options="${options} ${name}"
fi
done
_ret="${options}"
}
# get abstract flags in option
_get_option_abstract_flags() {
local name="${1}"
local toolkind="${2}"
local toolname="${3}"
local itemname="${4}"
local values="${5}"
if test_z "${values}"; then
_get_option_item "${name}" "${itemname}"; values="${_ret}"
fi
_get_abstract_flags "${toolkind}" "${toolname}" "${itemname}" "${values}"
}
# is config for option
is_config() {
if ! ${_loading_targets}; then
return 1
fi
local name=${1}
local value=${2}
_get_option_value "${name}"; local value_cur="${_ret}"
if test_eq "${value_cur}" "${value}"; then
return 0
fi
return 1
}
# has config for option
has_config() {
if ! ${_loading_targets}; then
return 1
fi
local name=${1}
_get_option_value "${name}"; local value_cur="${_ret}"
if _is_enabled ${value_cur}; then
return 0
fi
return 1
}
# set config for option, we can use it to modify option status when loading targets
set_config() {
local name=${1}
local value=${2}
_set_option_value "${name}" "${value}"
}
# set showmenu in option
set_showmenu() {
if ! ${_loading_options}; then
return
fi
local show="${1}"
_set_option_item "${_xmake_sh_option_current}" "showmenu" "${show}"
}
# set description in option
set_description() {
if ! ${_loading_options}; then
return
fi
local description="${1}"
_set_option_item "${_xmake_sh_option_current}" "description" "${description}"
}
# add cfuncs in option
add_cfuncs() {
if ! ${_loading_options}; then
return
fi
_add_option_item "${_xmake_sh_option_current}" "cfuncs" "${@}"
}
# add cxxfuncs in option
add_cxxfuncs() {
if ! ${_loading_options}; then
return
fi
_add_option_item "${_xmake_sh_option_current}" "cxxfuncs" "${@}"
}
# add cincludes in option
add_cincludes() {
if ! ${_loading_options}; then
return
fi
_add_option_item "${_xmake_sh_option_current}" "cincludes" "${@}"
}
# add cxxincludes in option
add_cxxincludes() {
if ! ${_loading_options}; then
return
fi
_add_option_item "${_xmake_sh_option_current}" "cxxincludes" "${@}"
}
# add ctypes in option
add_ctypes() {
if ! ${_loading_options}; then
return
fi
_add_option_item "${_xmake_sh_option_current}" "ctypes" "${@}"
}
# add cxxtypes in option
add_cxxtypes() {
if ! ${_loading_options}; then
return
fi
_add_option_item "${_xmake_sh_option_current}" "cxxtypes" "${@}"
}
# add csnippets in option
add_csnippets() {
if ! ${_loading_options}; then
return
fi
local csnippets="${1}"
_add_option_item "${_xmake_sh_option_current}" "csnippets" "${csnippets}"
}
# add cxxsnippets in option
add_cxxsnippets() {
if ! ${_loading_options}; then
return
fi
local cxxsnippets="${1}"
_add_option_item "${_xmake_sh_option_current}" "cxxsnippets" "${cxxsnippets}"
}
# before_check in option
before_check() {
if ! ${_loading_options}; then
return
fi
local funcname="${1}"
_add_option_item "${_xmake_sh_option_current}" "before_check" "${funcname}"
}
#-----------------------------------------------------------------------------
# target configuration apis
#
# define target
target() {
local name="${1}"
_xmake_sh_target_current="${name}"
if ! ${_loading_targets}; then
return
fi
if ! _map_has "targets" "${name}_name"; then
_xmake_sh_targets="${_xmake_sh_targets} ${name}"
fi
_map_set "targets" "${name}_name" "${name}"
return 0
}
target_end() {
_xmake_sh_target_current=""
}
_map "targets"
# has the given target?
_has_target() {
local name=${1}
if _map_has "targets" "${name}_name"; then
return 0
fi
return 1
}
# has the given target item
_has_target_item() {
local name=${1}
local key=${2}
if _map_has "targets" "${name}_${key}"; then
return 0
elif _map_has "targets" "__root_${key}"; then
return 0
fi
return 1
}
# get the given target item
_get_target_item() {
local name=${1}
local key=${2}
_map_get "targets" "${name}_${key}"
local values="${_ret}"
if _map_has "targets" "__root_${key}"; then
_map_get "targets" "__root_${key}"; local root_values="${_ret}"
if test_nz "${values}"; then
values="${root_values} ${values}"
else
values="${root_values}"
fi
fi
_ret="${values}"
}
# set the given target item
_set_target_item() {
local name=${1}
local key=${2}
shift
shift
if test_nz "${name}"; then
_map_set "targets" "${name}_${key}" "${@}"
else
_map_set "targets" "__root_${key}" "${@}"
fi
}
# add values to the given target item
_add_target_item() {
local name=${1}
local key=${2}
shift
shift
if test_nz "${name}"; then
_map_get "targets" "${name}_${key}"; local values="${_ret}"
values="${values} ${@}"
_map_set "targets" "${name}_${key}" "${values}"
else
_map_get "targets" "__root_${key}"; local values="${_ret}"
values="${values} ${@}"
_map_set "targets" "__root_${key}" "${values}"
fi
}
# is default?
_is_target_default() {
local name="${1}"
if _has_target_item "${name}" "default"; then
_get_target_item "${target}" "default"; local default="${_ret}"
if _is_enabled ${default}; then
return 0
fi
return 1
fi
return 0
}
# get target basename
_get_target_basename() {
local name="${1}"
_get_target_item "${name}" "basename"; local basename="${_ret}"
if test_z "${basename}"; then
basename="${name}"
fi
_ret="${basename}"
}
# get target extension
_get_target_extension() {
local name="${1}"
local extension=""
if _has_target_item "${name}" "extension"; then
_get_target_item "${name}" "extension"; extension="${_ret}"
elif is_plat "mingw"; then
_get_target_item "${name}" "kind"; local kind="${_ret}"
if test "x${kind}" = "xbinary"; then
extension=".exe"
elif test "x${kind}" = "xstatic"; then
extension=".a"
elif test "x${kind}" = "xshared"; then
extension=".dll"
fi
else
_get_target_item "${name}" "kind"; local kind="${_ret}"
if test "x${kind}" = "xstatic"; then
extension=".a"
elif test "x${kind}" = "xshared"; then
extension=".so"
fi
fi
_ret="${extension}"
}
# get target prefixname
_get_target_prefixname() {
local name="${1}"
local prefixname=""
if _has_target_item "${name}" "prefixname"; then
_get_target_item "${name}" "prefixname"; prefixname="${_ret}"
elif is_plat "mingw"; then
_get_target_item "${name}" "kind"; local kind="${_ret}"
if test "x${kind}" = "xstatic"; then
prefixname="lib"
elif test "x${kind}" = "xshared"; then
prefixname="lib"
fi
else
_get_target_item "${name}" "kind"; local kind="${_ret}"
if test "x${kind}" = "xstatic"; then
prefixname="lib"
elif test "x${kind}" = "xshared"; then
prefixname="lib"
fi
fi
_ret="${prefixname}"
}
# get target filename
_get_target_filename() {
local name="${1}"
_get_target_item "${name}" "filename"; local filename="${_ret}"
if test_z "${filename}"; then
_get_target_basename "${name}"; local basename="${_ret}"
_get_target_extension "${name}"; local extension="${_ret}"
_get_target_prefixname "${name}"; local prefixname="${_ret}"
filename="${prefixname}${basename}${extension}"
fi
_ret="${filename}"
}
# get target directory
_get_targetdir() {
local name="${1}"
_get_target_item "${name}" "targetdir"; local targetdir="${_ret}"
if test_z "${targetdir}"; then
targetdir="${xmake_sh_buildir}/${_target_plat}/${_target_arch}/${_target_mode}"
fi
_ret="${targetdir}"
}
# get target object directory
_get_target_objectdir() {
local name="${1}"
_get_target_item "${name}" "objectdir"; local objectdir="${_ret}"
if test_z "${objectdir}"; then
objectdir="${xmake_sh_buildir}/.objs/${name}/${_target_plat}/${_target_arch}/${_target_mode}"
fi
_ret="${objectdir}"
}
# get target file path
_get_target_file() {
local name="${1}"
_get_target_filename "${name}"; local filename="${_ret}"
_get_targetdir "${name}"; local targetdir="${_ret}"
local targetfile="${targetdir}/${filename}"
_ret="${targetfile}"
}
# get target librarydeps
_get_target_librarydeps_impl() {
local name="${1}"
local librarydeps=""
local dep=""
_get_target_item "${name}" "deps"; local deps="${_ret}"
for dep in ${deps}; do
_get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
librarydeps="${librarydeps} ${dep}"
_get_target_librarydeps_impl "${dep}"; local dep_librarydeps="${_ret}"
if test_nz "${dep_librarydeps}"; then
librarydeps="${librarydeps} ${dep_librarydeps}"
fi
fi
done
_ret="${librarydeps}"
}
_get_target_librarydeps() {
local name="${1}"
_get_target_item "${name}" "librarydeps"; local librarydeps="${_ret}"
if test_z "${librarydeps}" && test_nq "${librarydeps}" "__none__"; then
_get_target_librarydeps_impl "${name}"; librarydeps="${_ret}"
if test_nz "${librarydeps}"; then
_dedup_reverse "${librarydeps}"; librarydeps="${_ret}"
_set_target_item "${name}" "librarydeps" "${librarydeps}"
else
_set_target_item "${name}" "librarydeps" "__none__"
fi
fi
if test_eq "${librarydeps}" "__none__"; then
librarydeps=""
fi
_ret="${librarydeps}"
}
# get sourcefiles in target
_get_target_sourcefiles() {
local name="${1}"
_get_target_item "${name}" "files"
}
# get objectfile in target
_get_target_objectfile() {
local name="${1}"
local sourcefile="${2}"
local extension=".o"
if is_plat "mingw"; then
extension=".obj"
fi
_get_target_objectdir "${name}"; local objectdir="${_ret}"
local objectfile="${objectdir}/${sourcefile}${extension}"
_ret="${objectfile}"
}
# get objectfiles in target
_get_target_objectfiles() {
local name="${1}"
_get_target_sourcefiles "${name}"; local sourcefiles="${_ret}"
local objectfiles=""
local sourcefile=""
for sourcefile in ${sourcefiles}; do
_get_target_objectfile "${name}" "${sourcefile}"; local objectfile="${_ret}"
objectfiles="${objectfiles} ${objectfile}"
done
_ret="${objectfiles}"
}
# get abstract flags in target
_get_target_abstract_flags() {
local name="${1}"
local toolkind="${2}"
local toolname="${3}"
local itemname="${4}"
local values="${5}"
if test_z "${values}"; then
# get values from target
_get_target_item "${name}" "${itemname}"; values="${_ret}"
# get values from target deps
_get_target_librarydeps "${name}"; local deps="${_ret}"
local dep=""
for dep in ${deps}; do
_get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
_get_target_item "${dep}" "${itemname}_public"; local depvalues="${_ret}"
if test_nz "${depvalues}"; then
values="${values} ${depvalues}"
fi
fi
done
fi
if test_nz "${values}"; then
_get_abstract_flags "${toolkind}" "${toolname}" "${itemname}" "${values}"
else
_ret=""
fi
}
# get toolchain flags for ar in target
_get_target_toolchain_flags_for_ar() {
_ret="-cr"
}
# get toolchain flags for gcc in target
_get_target_toolchain_flags_for_gcc() {
local name="${1}"
local toolkind="${2}"
local flags=""
if is_arch "i386"; then
flags="${flags} -m32"
fi
_get_target_item "${name}" "kind"; local targetkind="${_ret}"
if test_eq "${targetkind}" "shared"; then
if test_eq "${toolkind}" "sh"; then
flags="${flags} -shared -fPIC"
elif test_eq "${toolkind}" "cc" || test_eq "${toolkind}" "cxx"; then
flags="${flags} -fPIC"
fi
fi
_ret="${flags}"
}
# get toolchain flags for clang in target
_get_target_toolchain_flags_for_clang() {
local name="${1}"
local toolkind="${2}"
local flags="-Qunused-arguments"
if is_arch "i386"; then
flags="${flags} -m32"
fi
_get_target_item "${name}" "kind"; local targetkind="${_ret}"
if test_eq "${targetkind}" "shared"; then
if test_eq "${toolkind}" "sh"; then
flags="${flags} -shared -fPIC"
elif test_eq "${toolkind}" "cc" || test_eq "${toolkind}" "cxx"; then
flags="${flags} -fPIC"
fi
fi
if is_plat "macosx"; then
_os_iorunv "xcrun" "-sdk" "macosx" "--show-sdk-path"; local sdkdir="${_ret}"
if test_nz "${sdkdir}"; then
flags="${flags} -isysroot \"${sdkdir}\""
fi
fi
_ret="${flags}"
}
# get toolchain flags in target
_get_target_toolchain_flags() {
local name="${1}"
local toolkind="${2}"
local toolname="${3}"
local flags=""
case "${toolname}" in
gcc) _get_target_toolchain_flags_for_gcc "${name}" "${toolkind}"; flags="${_ret}";;
gxx) _get_target_toolchain_flags_for_gcc "${name}" "${toolkind}"; flags="${_ret}";;
clang) _get_target_toolchain_flags_for_clang "${name}" "${toolkind}"; flags="${_ret}";;
clangxx) _get_target_toolchain_flags_for_clang "${name}" "${toolkind}"; flags="${_ret}";;
emcc) _get_target_toolchain_flags_for_clang "${name}" "${toolkind}"; flags="${_ret}";;
emxx) _get_target_toolchain_flags_for_clang "${name}" "${toolkind}"; flags="${_ret}";;
ar) _get_target_toolchain_flags_for_ar "${name}" "${toolkind}"; flags="${_ret}";;
emar) _get_target_toolchain_flags_for_ar "${name}" "${toolkind}"; flags="${_ret}";;
*) raise "unknown toolname(${toolname})!" ;;
esac
_ret="${flags}"
}
# get compiler flags in target
_get_target_compiler_flags() {
local name="${1}"
local toolkind="${2}"
_get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
local result=""
# get toolchain flags
_get_target_toolchain_flags "${name}" "${toolkind}" "${toolname}"; local toolchain_flags="${_ret}"
if test_nz "${toolchain_flags}"; then
result="${result} ${toolchain_flags}"
fi
# get abstract flags
local itemnames="symbols optimizes warnings languages defines undefines includedirs frameworkdirs frameworks"
local itemname=""
for itemname in ${itemnames}; do
_get_target_abstract_flags "${name}" "${toolkind}" "${toolname}" "${itemname}"; local flags="${_ret}"
if test_nz "${flags}"; then
result="${result} ${flags}"
fi
done
# get raw flags, e.g. add_cflags, add_cxxflags
_get_flagname "${toolkind}"; local flagname="${_ret}"
_get_target_item "${name}" "${flagname}"; local flags="${_ret}"
# get flags from target deps
_get_target_librarydeps "${name}"; local deps="${_ret}"
local dep=""
for dep in ${deps}; do
_get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
_get_target_item "${dep}" "${flagname}_public"; local depflags="${_ret}"
if test_nz "${depflags}"; then
flags="${flags} ${depflags}"
fi
fi
done
if test_nz "${flags}"; then
result="${result} ${flags}"
fi
if test_eq "${flagname}" "cflags" || test_eq "${flagname}" "cxxflags"; then
_get_target_item "${name}" "cxflags"; flags="${_ret}"
if test_nz "${flags}"; then
result="${result} ${flags}"
fi
elif test_eq "${flagname}" "mflags" || test_eq "${flagname}" "mxxflags"; then
_get_target_item "${name}" "mxflags"; flags="${_ret}"
if test_nz "${flags}"; then
result="${result} ${flags}"
fi
fi
# get flags from environments, e.g. $CFLAGS, $CXXFLAGS
if test_nz "${CPPFLAGS}"; then
result="${result} ${CPPFLAGS}"
fi
if test_eq "${flagname}" "cflags" && test_nz "${CFLAGS}"; then
result="${result} ${CFLAGS}"
fi
if test_eq "${flagname}" "cxxflags" && test_nz "${CXXFLAGS}"; then
result="${result} ${CXXFLAGS}"
fi
if test_eq "${flagname}" "mflags" && test_nz "${MFLAGS}"; then
result="${result} ${MFLAGS}"
fi
if test_eq "${flagname}" "mxxflags" && test_nz "${MXXFLAGS}"; then
result="${result} ${MXXFLAGS}"
fi
_ret="${result}"
}
# get linker flags in target
_get_target_linker_flags() {
local name="${1}"
local toolkind="${2}"
_get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
local result=""
# get toolchain flags
_get_target_toolchain_flags "${name}" "${toolkind}" "${toolname}"; local toolchain_flags="${_ret}"
if test_nz "${toolchain_flags}"; then
result="${result} ${toolchain_flags}"
fi
# get flags from target deps
_get_target_librarydeps "${name}"; local deps="${_ret}"
local dep=""
for dep in ${deps}; do
_get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
_get_targetdir "${dep}"; local dep_targetdir="${_ret}"
_get_target_basename "${dep}"; local dep_basename="${_ret}"
_get_target_abstract_flags "${dep}" "${toolkind}" "${toolname}" "linkdirs" "${dep_targetdir}"; local linkdirs_flags="${_ret}"
_get_target_abstract_flags "${dep}" "${toolkind}" "${toolname}" "links" "${dep_basename}"; local links_flags="${_ret}"
if test_eq "${dep_kind}" "shared"; then
local rpathdir="@loader_path"
_get_targetdir "${name}"; local targetdir="${_ret}"
path_relative "${targetdir}" "${dep_targetdir}"; local subdir="${_ret}"
if test_nz "${subdir}"; then
rpathdir="${rpathdir}/${subdir}"
fi
_get_target_abstract_flags "${dep}" "${toolkind}" "${toolname}" "rpathdirs" "${rpathdir}"; local rpathdirs_flags="${_ret}"
result="${result} ${rpathdirs_flags}"
fi
result="${result} ${linkdirs_flags} ${links_flags}"
fi
done
# get abstract flags
local itemnames="strip frameworkdirs linkdirs links rpathdirs frameworks syslinks"
local itemname=""
for itemname in ${itemnames}; do
_get_target_abstract_flags "${name}" "${toolkind}" "${toolname}" "${itemname}"; local flags="${_ret}"
if test_nz "${flags}"; then
result="${result} ${flags}"
fi
done
# get raw flags, e.g. add_ldflags, add_shflags
_get_flagname "${toolkind}"; local flagname="${_ret}"
_get_target_item "${name}" "${flagname}"; local flags="${_ret}"
# get flags from target deps
for dep in ${deps}; do
_get_target_item "${dep}" "kind"; local dep_kind="${_ret}"
if test_eq "${dep_kind}" "static" || test_eq "${dep_kind}" "shared"; then
_get_target_item "${dep}" "${flagname}_public"; local depflags="${_ret}"
if test_nz "${depflags}"; then
flags="${flags} ${depflags}"
fi
fi
done
if test_nz "${flags}"; then
result="${result} ${flags}"
fi
# get flags from environments, e.g. $LDFLAGS
if test_eq "${flagname}" "ldflags" && test_nz "${LDFLAGS}"; then
result="${result} ${LDFLAGS}"
fi
if test_eq "${flagname}" "shflags" && test_nz "${LDFLAGS}"; then
result="${result} ${LDFLAGS}"
fi
_ret="${result}"
}
# get archiver flags in target
_get_target_archiver_flags() {
local name="${1}"
local toolkind="${2}"
_get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
local result=""
# get toolchain flags
_get_target_toolchain_flags "${name}" "${toolkind}" "${toolname}"; local toolchain_flags="${_ret}"
if test_nz "${toolchain_flags}"; then
result="${result} ${toolchain_flags}"
fi
# get raw flags, e.g. add_arflags
_get_flagname "${toolkind}"; local flagname="${_ret}"
_get_target_item "${name}" "${flagname}"; local flags="${_ret}"
if test_nz "${flags}"; then
result="${result} ${flags}"
fi
_ret="${result}"
}
# get target flags
_get_target_flags() {
local name="${1}"
local toolkind="${2}"
local flags=""
if test_eq "${toolkind}" "sh"; then
_get_target_linker_flags "${name}" "${toolkind}"; flags="${_ret}"
elif test_eq "${toolkind}" "ld"; then
_get_target_linker_flags "${name}" "${toolkind}"; flags="${_ret}"
elif test_eq "${toolkind}" "ar"; then
_get_target_archiver_flags "${name}" "${toolkind}"; flags="${_ret}"
else
_get_target_compiler_flags "${name}" "${toolkind}"; flags="${_ret}"
fi
_ret="${flags}"
}
# add file paths in target
_add_target_filepaths() {
local key="$1"
shift
# we need avoid escape `*` automatically in for-loop
local file=""
string_replace "${@}" "\*" "?"; local list="${_ret}"
if test_eq "${key}" "files"; then
for file in ${list}; do
path_sourcekind "${file}"; local sourcekind="${_ret}"
_targets_toolkinds="${_targets_toolkinds} ${sourcekind}"
done
fi
for file in ${list}; do
string_replace "${file}" "?" "*"; file="${_ret}"
if ! path_is_absolute "${file}"; then
file="${xmake_sh_scriptdir}/${file}"
fi
local files=""
if string_contains_star2 "${file}"; then
path_directory "${file}"; local dir="${_ret}"
path_filename_fromdir "${file}" "${dir}"; local name="${_ret}"
_os_find "${dir}" "${name}"; files="${_ret}"
elif string_contains_star "${file}"; then
path_directory "${file}"; local dir="${_ret}"
path_filename_fromdir "${file}" "${dir}"; local name="${_ret}"
_os_find "${dir}" "${name}" 1; files="${_ret}"
else
files="${file}"
fi
for file in ${files}; do
path_relative "${xmake_sh_projectdir}" "${file}"; file="${_ret}"
_add_target_item "${_xmake_sh_target_current}" "${key}" "${file}"
done
done
}
# add install paths in target
_add_target_installpaths() {
local key="$1"
local filepattern="${2}"
local prefixdir="${3}"
local filename=${4}
# get root directory, e.g. "src/foo/(*.h)" -> "src/foo"
local rootdir=""
if string_contains "${filepattern}" "("; then
string_split "${filepattern}" "(" 1; rootdir="${_ret}"
rootdir=${rootdir%/}
if ! path_is_absolute "${rootdir}"; then
rootdir="${xmake_sh_scriptdir}/${rootdir}"
fi
path_relative "${xmake_sh_projectdir}" "${rootdir}"; rootdir="${_ret}"
rootdir=${rootdir%/}
fi
# remove (), e.g. "src/(*.h)" -> "src/*.h"
string_replace ${filepattern} "(" ""; filepattern="${_ret}"
string_replace ${filepattern} ")" ""; filepattern="${_ret}"
# get real path
if ! path_is_absolute "${filepattern}"; then
filepattern="${xmake_sh_scriptdir}/${filepattern}"
fi
local files=""
if string_contains_star2 "${filepattern}"; then
path_directory "${filepattern}"; local dir="${_ret}"
path_filename_fromdir "${filepattern}" "${dir}"; local name="${_ret}"
_os_find "${dir}" "${name}"; files="${_ret}"
elif string_contains_star "${filepattern}"; then
path_directory "${filepattern}"; local dir="${_ret}"
path_filename_fromdir "${filepattern}" "${dir}"; local name="${_ret}"
_os_find "${dir}" "${name}" 1; files="${_ret}"
else
files="${filepattern}"
fi
for file in ${files}; do
path_relative "${xmake_sh_projectdir}" "${file}"; file="${_ret}"
_add_target_item "${_xmake_sh_target_current}" "${key}" "${file}:${rootdir}:${prefixdir}:${filename}"
done
}
# set target file path
_set_target_filepath() {
local key="${1}"
local path="${2}"
if ! path_is_absolute "${path}"; then
path="${xmake_sh_scriptdir}/${path}"
fi
path_relative ${xmake_sh_projectdir} "${path}"; path="${_ret}"
_set_target_item "${_xmake_sh_target_current}" "${key}" "${path}"
}
# set kind in target
set_kind() {
if ! ${_loading_targets}; then
return
fi
local kind=${1}
_set_target_item "${_xmake_sh_target_current}" "kind" "${kind}"
case "${kind}" in
binary) _targets_toolkinds="${_targets_toolkinds} ld";;
static) _targets_toolkinds="${_targets_toolkinds} ar";;
shared) _targets_toolkinds="${_targets_toolkinds} sh";;
*) raise "unknown target kind ${kind}";;
esac
}
# set version in target
set_version() {
if ! ${_loading_targets}; then
return
fi
local version="${1}"
local version_build="${2}"
_set_target_item "${_xmake_sh_target_current}" "version" "${version}"
_set_target_item "${_xmake_sh_target_current}" "version_build" "${version_build}"
}
# set default in target
set_default() {
local default=${1}
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_set_target_item "${_xmake_sh_target_current}" "default" "${default}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_set_option_item "${_xmake_sh_option_current}" "default" "${default}"
fi
}
# set configvar in target
set_configvar() {
if ! ${_loading_targets}; then
return
fi
local name="${1}"
local value="${2}"
_set_target_item "${_xmake_sh_target_current}" "configvar_${name}" "${value}"
_add_target_item "${_xmake_sh_target_current}" "configvars" "${name}"
}
# set filename in target
set_filename() {
if ! ${_loading_targets}; then
return
fi
local filename="${1}"
_set_target_item "${_xmake_sh_target_current}" "filename" "${filename}"
}
# set basename in target
set_basename() {
if ! ${_loading_targets}; then
return
fi
local basename="${1}"
_set_target_item "${_xmake_sh_target_current}" "basename" "${basename}"
}
# set extension in target
set_extension() {
if ! ${_loading_targets}; then
return
fi
local extension=${1}
_set_target_item "${_xmake_sh_target_current}" "extension" "${extension}"
}
# set prefixname in target
set_prefixname() {
if ! ${_loading_targets}; then
return
fi
local prefixname=${1}
_set_target_item "${_xmake_sh_target_current}" "prefixname" "${prefixname}"
}
# set target directory
set_targetdir() {
if ! ${_loading_targets}; then
return
fi
_set_target_filepath "targetdir" "${1}"
}
# set target object directory
set_objectdir() {
if ! ${_loading_targets}; then
return
fi
_set_target_filepath "objectdir" "${1}"
}
# set target config directory
set_configdir() {
if ! ${_loading_targets}; then
return
fi
_set_target_filepath "configdir" "${1}"
}
# set target install directory
set_installdir() {
if ! ${_loading_targets}; then
return
fi
_set_target_filepath "installdir" "${1}"
}
# add deps in target
add_deps() {
if ! ${_loading_targets}; then
return
fi
_add_target_item "${_xmake_sh_target_current}" "deps" "${@}"
}
# add files in target
add_files() {
if ! ${_loading_targets}; then
return
fi
_add_target_filepaths "files" "$@"
}
# add install files in target
add_installfiles() {
if ! ${_loading_targets}; then
return
fi
_add_target_installpaths "installfiles" "$@"
}
# add header files in target
add_headerfiles() {
if ! ${_loading_targets}; then
return
fi
_add_target_installpaths "headerfiles" "$@"
}
# add config files in target
add_configfiles() {
if ! ${_loading_targets}; then
return
fi
_add_target_filepaths "configfiles" "$@"
}
# add defines in target
add_defines() {
local define=""
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
local public=false
for define in $@; do
if test_nq "${define}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "defines" "${define}"
else
public=true
fi
done
if ${public}; then
for define in $@; do
if test_nq "${define}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "defines_public" "${define}"
fi
done
fi
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "defines" "${@}"
fi
}
# add undefines in target
add_undefines() {
local undefine=""
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
local public=false
for undefine in $@; do
if test_nq "${undefine}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "undefines" "${undefine}"
else
public=true
fi
done
if ${public}; then
for undefine in $@; do
if test_nq "${undefine}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "undefines_public" "${undefine}"
fi
done
fi
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "undefines" "${@}"
fi
}
# add includedirs in target
add_includedirs() {
local public=false
local dir=""
for dir in $@; do
if test_nq "${dir}" "{public}"; then
if ! path_is_absolute "${dir}"; then
dir="${xmake_sh_scriptdir}/${dir}"
fi
if string_startswith "${dir}" "${xmake_sh_projectdir}"; then
path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
fi
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "includedirs" "${dir}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "includedirs" "${dir}"
fi
else
public=true
fi
done
if ${public}; then
for dir in $@; do
if test_nq "${dir}" "{public}"; then
if ! path_is_absolute "${dir}"; then
dir="${xmake_sh_scriptdir}/${dir}"
fi
if string_startswith "${dir}" "${xmake_sh_projectdir}"; then
path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
fi
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "includedirs_public" "${dir}"
fi
fi
done
fi
}
# add links in target
add_links() {
local link=""
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
local public=false
for link in $@; do
if test_nq "${link}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "links" "${link}"
else
public=true
fi
done
if ${public}; then
for link in $@; do
if test_nq "${link}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "links_public" "${link}"
fi
done
fi
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "links" "${@}"
fi
}
# add syslinks in target
add_syslinks() {
local syslink=""
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
local public=false
for syslink in $@; do
if test_nq "${syslink}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "syslinks" "${syslink}"
else
public=true
fi
done
if ${public}; then
for syslink in $@; do
if test_nq "${syslink}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "syslinks_public" "${syslink}"
fi
done
fi
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "syslinks" "${@}"
fi
}
# add linkdirs in target
add_linkdirs() {
local dir=""
local public=false
for dir in $@; do
if test_nq "${dir}" "{public}"; then
if ! path_is_absolute "${dir}"; then
dir="${xmake_sh_scriptdir}/${dir}"
fi
if string_startswith "${dir}" "${xmake_sh_projectdir}"; then
path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
fi
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "linkdirs" "${dir}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "linkdirs" "${dir}"
fi
else
public=true
fi
done
if ${public}; then
for dir in $@; do
if test_nq "${dir}" "{public}"; then
if ! path_is_absolute "${dir}"; then
dir="${xmake_sh_scriptdir}/${dir}"
fi
if string_startswith "${dir}" "${xmake_sh_projectdir}"; then
path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
fi
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "linkdirs_public" "${dir}"
fi
fi
done
fi
}
# add rpathdirs in target
add_rpathdirs() {
if ! ${_loading_targets}; then
return
fi
local dir=""
for dir in $@; do
if ! path_is_absolute "${dir}"; then
dir="${xmake_sh_scriptdir}/${dir}"
fi
path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
_add_target_item "${_xmake_sh_target_current}" "rpathdirs" "${dir}"
done
}
# add frameworks in target
add_frameworks() {
local framework=""
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
local public=false
for framework in $@; do
if test_nq "${framework}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "frameworks" "${framework}"
else
public=true
fi
done
if ${public}; then
for framework in $@; do
if test_nq "${framework}" "{public}"; then
_add_target_item "${_xmake_sh_target_current}" "frameworks_public" "${framework}"
fi
done
fi
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "frameworks" "${@}"
fi
}
# add frameworkdirs in target
add_frameworkdirs() {
local dir=""
for dir in $@; do
if ! path_is_absolute "${dir}"; then
dir="${xmake_sh_scriptdir}/${dir}"
fi
path_relative ${xmake_sh_projectdir} "${dir}"; dir="${_ret}"
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "frameworkdirs" "${dir}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "frameworkdirs" "${dir}"
fi
done
}
# set strip in target
set_strip() {
if ! ${_loading_targets}; then
return
fi
local strip=${1}
_set_target_item "${_xmake_sh_target_current}" "strip" "${strip}"
}
# set symbols in target
set_symbols() {
if ! ${_loading_targets}; then
return
fi
local symbols="${1}"
_set_target_item "${_xmake_sh_target_current}" "symbols" "${symbols}"
}
# set languages in target
set_languages() {
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_set_target_item "${_xmake_sh_target_current}" "languages" "${@}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_set_option_item "${_xmake_sh_option_current}" "languages" "${@}"
fi
}
# set warnings in target
set_warnings() {
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_set_target_item "${_xmake_sh_target_current}" "warnings" "${@}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_set_option_item "${_xmake_sh_option_current}" "warnings" "${@}"
fi
}
# set optimizes in target
set_optimizes() {
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_set_target_item "${_xmake_sh_target_current}" "optimizes" "${@}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_set_option_item "${_xmake_sh_option_current}" "optimizes" "${@}"
fi
}
# add cflags in target
add_cflags() {
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "cflags" "${@}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "cflags" "${@}"
fi
}
# add cxflags in target
add_cxflags() {
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "cxflags" "${@}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "cxflags" "${@}"
fi
}
# add cxxflags in target
add_cxxflags() {
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "cxxflags" "${@}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "cxxflags" "${@}"
fi
}
# add asflags in target
add_asflags() {
if ! ${_loading_targets}; then
return
fi
_add_target_item "${_xmake_sh_target_current}" "asflags" "${@}"
}
# add mflags in target
add_mflags() {
if ! ${_loading_targets}; then
return
fi
_add_target_item "${_xmake_sh_target_current}" "mflags" "${@}"
}
# add mxflags in target
add_mxflags() {
if ! ${_loading_targets}; then
return
fi
_add_target_item "${_xmake_sh_target_current}" "mxflags" "${@}"
}
# add mxxflags in target
add_mxxflags() {
if ! ${_loading_targets}; then
return
fi
_add_target_item "${_xmake_sh_target_current}" "mxxflags" "${@}"
}
# add ldflags in target
add_ldflags() {
if ${_loading_targets} && test_z "${_xmake_sh_option_current}"; then
_add_target_item "${_xmake_sh_target_current}" "ldflags" "${@}"
elif ${_loading_options} && test_nz "${_xmake_sh_option_current}"; then
_add_option_item "${_xmake_sh_option_current}" "ldflags" "${@}"
fi
}
# add shflags in target
add_shflags() {
if ! ${_loading_targets}; then
return
fi
_add_target_item "${_xmake_sh_target_current}" "shflags" "${@}"
}
# add arflags in target
add_arflags() {
if ! ${_loading_targets}; then
return
fi
_add_target_item "${_xmake_sh_target_current}" "arflags" "${@}"
}
# add options in target
add_options() {
if ! ${_loading_targets}; then
return
fi
local name=""
local public=false
for name in $@; do
if test_nq "${name}" "{public}"; then
public=true
break
fi
done
for name in $@; do
if has_config "${name}"; then
local itemname=""
local itemnames="includedirs linkdirs links defines cflags cxflags cxxflags ldflags"
for itemname in ${itemnames}; do
_get_option_item "${name}" "${itemname}"; local values="${_ret}"
if test_nz "${values}"; then
_add_target_item "${_xmake_sh_target_current}" "${itemname}" "${values}"
if $public; then
_add_target_item "${_xmake_sh_target_current}" "${itemname}_public" "${values}"
fi
fi
done
fi
done
}
#-----------------------------------------------------------------------------
# toolchain configuration apis
#
# define toolchain
toolchain() {
local name="${1}"
_xmake_sh_toolchain_current="${name}"
if ! ${_loading_toolchains}; then
return
fi
_xmake_sh_toolchains="${_xmake_sh_toolchains} ${name}"
_map_set "toolchains" "${name}_name" "${name}"
return 0
}
toolchain_end() {
_xmake_sh_toolchain_current=""
}
_map "toolchains"
# has the given toolchain?
_has_toolchain() {
local name=${1}
if _map_has "toolchains" "${name}_name"; then
return 0
fi
return 1
}
# get the given toolchain item
_get_toolchain_item() {
local name=${1}
local key=${2}
_map_get "toolchains" "${name}_${key}"
}
# set the given toolchain item
_set_toolchain_item() {
local name=${1}
local key=${2}
local value=${3}
if test_nz "${name}"; then
_map_set "toolchains" "${name}_${key}" "${value}"
else
raise "please set toolchain in the toolchain scope!"
fi
}
# get the give toolchain toolset
_get_toolchain_toolset() {
local name=${1}
local kind=${2}
_get_toolchain_item "${name}" "toolset_${kind}"
}
# set the give toolchain toolset
_set_toolchain_toolset() {
local name=${1}
local kind=${2}
local programs="${3}"
_set_toolchain_item "${name}" "toolset_${kind}" "${programs}"
}
# add the give toolchain toolset
_add_toolchain_toolset() {
local name=${1}
local kind=${2}
local program="${3}"
_get_toolchain_item "${name}" "toolset_${kind}"; local programs="${_ret}"
if test_nz "${programs}"; then
programs="${programs}:${program}"
else
programs="${program}"
fi
_set_toolchain_item "${name}" "toolset_${kind}" "${programs}"
}
# set toolset in toolchain
set_toolset() {
if ! ${_loading_toolchains}; then
return
fi
local kind=${1}
shift
local idx=0
while test $# != 0; do
local program="${1}"
local key="${kind}"
if test_nq "${idx}" "0"; then
key="${key}_${idx}"
fi
_set_toolchain_toolset "${_xmake_sh_toolchain_current}" "${key}" "${program}"
idx=$((idx+1))
shift
done
}
#-----------------------------------------------------------------------------
# load options
#
# load options and toolchains
_load_options_and_toolchains() {
_loading_options=true
_loading_toolchains=true
_loading_targets=false
local file=${xmake_sh_projectdir}/xmake.sh
if test -f "${file}"; then
includes "${file}"
else
# include all xmake.sh files in next sub-directories
local files=`find ${xmake_sh_projectdir} -maxdepth 2 -mindepth 2 -name "xmake.sh"`
for file in ${files}; do
includes "${file}"
done
fi
}
_load_options_and_toolchains
# show option usage
_show_options_usage() {
_get_options_for_menu; local options="${_ret}"
for name in ${options}; do
_get_option_item "${name}" "description"; local description="${_ret}"
_get_option_item "${name}" "default"; local default="${_ret}"
string_toupper ${name}; local head="--${name}="${_ret}""
local headsize=${#head}
local tail="${description}"
if test "x${default}" != "x"; then
local defval=${default}
if test "x${defval}" = "xtrue"; then
defval="yes"
elif test "x${defval}" = "xfalse"; then
defval="no"
fi
tail="${tail} (default: ${defval})"
fi
local width=24
local padding_width=$((${width} - ${headsize}))
local padding=$(string_dupch ${padding_width} " ")
echo " ${head}${padding}${tail}"
done
}
# show configure usage
_show_usage() {
echo '
Usage: '"$0"' [<options>...]
Options: [defaults in brackets after descriptions]
Common options:
--help Print this message.
--version Only print version information.
--verbose Display more information.
--diagnosis Display lots of diagnosis information.
--generator=GENERATOR Set the project generator. (default: '"${_project_generator}"')
- gmake
- ninja
--make=MAKE Set the make program. (default: '"${_make_program_default}"')
--ninja=NINJA Set the Ninja program. (default: '"${_ninja_program_default}"')
--plat=PLAT Compile for the given platform. (default: '"${_target_plat_default}"')
- msys
- cross
- bsd
- mingw
- macosx
- linux
--arch=ARCH Compile for the given architecture. (default: '"${_target_arch_default}"')
- msys: i386 x86_64
- cross: i386 x86_64 arm arm64 mips mips64 riscv riscv64 s390x ppc ppc64 sh4
- bsd: i386 x86_64
- mingw: i386 x86_64 arm arm64
- macosx: x86_64 arm64
- linux: i386 x86_64 armv7 armv7s arm64-v8a mips mips64 mipsel mips64el
--mode=MODE Set the given compilation mode. (default: '"${_target_mode_default}"')
- release
- debug
--kind=KIND Set the given target kind. (default: '"${_target_kind_default}"')
- static
- shared
- binary
--toolchain=TOOLCHAIN Set toolchain name.
- clang
- gcc
--buildir=DIR Set build directory. (default: '"${xmake_sh_buildir}"')
Autoconf options:
--build=BUILD Configure for building on BUILD [guessed]
--host=HOST Cross-compile to build programs to run on HOST [BUILD]
--prefix=PREFIX Set install files directory in tree rooted at PREFIX. (default: '"${_install_prefix_default}"')
--bindir=DIR Set install binaries directory in PREFIX/DIR. (default: '"${_install_bindir_default}"')
--libdir=DIR Set install libraries directory in PREFIX/DIR. (default: '"${_install_libdir_default}"')
--includedir=DIR Set install includes directory in PREFIX/DIR. (default: '"${_install_includedir_default}"')
Project options:
'"$(_show_options_usage)"'
'
exit 1
}
# show xmake.sh version
_show_version() {
echo "xmake.sh v${xmake_sh_version}, A script-only build utility like autotools"
echo "${xmake_sh_copyright}"
echo ' _ _ '
echo " __ ___ __ __ __ _| | ______ ___| |__ "
echo " \ \/ / | \/ |/ _ | |/ / __ \ / __| '_ \ "
echo " > < | \__/ | /_| | < ___/_\__ \ | | | "
echo " /_/\_\_|_| |_|\__ \|_|\_\____(_)___/_| |_| "
echo ' by ruki, xmake.io'
echo ' '
echo ' 👉 Manual: https://xmake.io/#/getting_started '
echo ' 🙏 Donate: https://xmake.io/#/sponsor '
echo ' '
exit 2
}
# --foo=yes => foo
_parse_argument_name() {
_ret=$(echo "${1#*--}" | sed "s/${2-=[^=]*}$//")
string_replace "${_ret}" "-" "_"
}
# --foo=yes => yes
_parse_argument_value() {
_ret=$(echo "$1" | sed "s/^${2-[^=]*=}//")
}
# parse input arguments
_handle_option() {
_parse_argument_name ${1}; local name="${_ret}"
_parse_argument_value ${1}; local value="${_ret}"
if test_eq "${name}" "help"; then
_show_usage
return 0
elif test_eq "${name}" "version"; then
_show_version
return 0
elif test_eq "${name}" "verbose"; then
xmake_sh_verbose=true
return 0
elif test_eq "${name}" "diagnosis"; then
xmake_sh_diagnosis=true
return 0
elif test_eq "${name}" "plat"; then
_target_plat=${value}
return 0
elif test_eq "${name}" "arch"; then
_target_arch=${value}
return 0
elif test_eq "${name}" "mode"; then
_target_mode=${value}
return 0
elif test_eq "${name}" "kind"; then
_target_kind=${value}
return 0
elif test_eq "${name}" "toolchain"; then
_target_toolchain=${value}
return 0
elif test_eq "${name}" "generator"; then
_project_generator=${value}
return 0
elif test_eq "${name}" "make"; then
_make_program=${value}
return 0
elif test_eq "${name}" "ninja"; then
_ninja_program=${value}
return 0
elif test_eq "${name}" "prefix"; then
_install_prefix_default="${value}"
return 0
elif test_eq "${name}" "bindir"; then
_install_bindir_default="${value}"
return 0
elif test_eq "${name}" "libdir"; then
_install_libdir_default="${value}"
return 0
elif test_eq "${name}" "includedir"; then
_install_includedir_default="${value}"
return 0
elif test_eq "${name}" "buildir"; then
xmake_sh_buildir="${value}"
return 0
elif test_eq "${name}" "build"; then
_autoconf_build_type="${value}"
return 0
elif test_eq "${name}" "host"; then
_autoconf_host_type="${value}"
return 0
elif _has_option "${name}"; then
_set_option_value "${name}" "${value}"
return 0
fi
return 1
}
while test $# != 0; do
if ! _handle_option ${1}; then
wprint "unknown option: $1"
fi
shift
done
#-----------------------------------------------------------------------------
# handle some autoconf configurations
#
# parse triplet
# https://github.com/xmake-io/xmake/issues/3869
# e.g. i686-linux-gnu, aarch64-apple-darwin, x86_64-w64-mingw32, i686-redhat-linux-gnu
_parse_triplet() {
local triplet="${1}"
string_split "${triplet}" "-"
}
_get_arch_from_cpu() {
local cpu="${1}"
case "${cpu}" in
i686) _ret="i386";;
i386) _ret="i386";;
x86_64) _ret="x86_64";;
aarch64) _ret="arm64";;
arm64) _ret="arm64";;
arm*) _ret="arm";;
*) _ret="${cpu}";;
esac
}
_get_plat_from_vendor_os() {
local vendor="${1}"
local os="${2}"
case "${vendor}" in
linux)
if string_contains "${os}" "android"; then
_ret="android"
else
_ret="linux"
fi
;;
apple)
if test_eq "${os}" "darwin"; then
_ret="macosx"
fi
;;
w64) _ret="mingw";;
*) _ret="${os}";;
esac
}
_handle_autoconf_configs() {
if test_z "${_autoconf_host_type}"; then
_autoconf_host_type="${_autoconf_build_type}"
fi
if test_nz "${_autoconf_build_type}"; then
_parse_triplet "${_autoconf_build_type}"; local cpu="${_ret}"; local vendor="${_ret2}"; local os="${_ret3}"
_get_arch_from_cpu "${cpu}"
if test_nz "${_ret}"; then
os_arch="${_ret}"
else
wprint "unknown cpu: ${cpu} in --build=${value}"
fi
_get_plat_from_vendor_os "${vendor}" "${os}"
if test_nz "${_ret}"; then
os_host="${_ret}"
else
wprint "unknown vendor-os: ${vendor}-${os} in --build=${value}"
fi
fi
if test_nz "${_autoconf_host_type}"; then
_parse_triplet "${_autoconf_host_type}"; local cpu="${_ret}"; local vendor="${_ret2}"; local os="${_ret3}"
_get_arch_from_cpu "${cpu}"
if test_nz "${_ret}"; then
_target_arch_default="${_ret}"
else
wprint "unknown cpu: ${cpu} in --host=${value}"
fi
_get_plat_from_vendor_os "${vendor}" "${os}"
if test_nz "${_ret}"; then
_target_plat_default="${_ret}"
else
wprint "unknown vendor-os: ${vendor}-${os} in --build=${value}"
fi
fi
}
_handle_autoconf_configs
#-----------------------------------------------------------------------------
# detect platform and toolchains
#
# envs toolchain
toolchain "envs"
set_toolset "as" "$CC" "$CXX" "$AS"
set_toolset "cc" "$CC"
set_toolset "cxx" "$CC" "$CXX"
set_toolset "mm" "$CC" "$CXX"
set_toolset "mxx" "$CC" "$CXX"
set_toolset "ld" "$CXX" "$CC" "$LD"
set_toolset "sh" "$CXX" "$CC" "$LD"
set_toolset "ar" "$AR" "ar"
toolchain_end
# clang toolchain
toolchain "clang"
set_toolset "as" "clang"
set_toolset "cc" "clang"
set_toolset "cxx" "clang" "clang++"
set_toolset "mm" "clang"
set_toolset "mxx" "clang" "clang++"
set_toolset "ld" "clang++" "clang"
set_toolset "sh" "clang++" "clang"
set_toolset "ar" "ar"
toolchain_end
# gcc toolchain
toolchain "gcc"
set_toolset "as" "gcc"
set_toolset "cc" "gcc"
set_toolset "cxx" "gcc" "g++"
set_toolset "mm" "gcc"
set_toolset "mxx" "gcc" "g++"
set_toolset "ld" "g++" "gcc"
set_toolset "sh" "g++" "gcc"
set_toolset "ar" "ar"
toolchain_end
# mingw toolchain (x86_64)
toolchain "x86_64_w64_mingw32"
set_toolset "as" "x86_64-w64-mingw32-gcc"
set_toolset "cc" "x86_64-w64-mingw32-gcc"
set_toolset "cxx" "x86_64-w64-mingw32-gcc" "x86_64-w64-mingw32-g++"
set_toolset "mm" "x86_64-w64-mingw32-gcc"
set_toolset "mxx" "x86_64-w64-mingw32-gcc" "x86_64-w64-mingw32-g++"
set_toolset "ld" "x86_64-w64-mingw32-g++" "x86_64-w64-mingw32-gcc"
set_toolset "sh" "x86_64-w64-mingw32-g++" "x86_64-w64-mingw32-gcc"
set_toolset "ar" "x86_64-w64-mingw32-ar" "ar"
toolchain_end
# mingw toolchain (i686)
toolchain "i686_w64_mingw32"
set_toolset "as" "i686-w64-mingw32-gcc"
set_toolset "cc" "i686-w64-mingw32-gcc"
set_toolset "cxx" "i686-w64-mingw32-gcc" "i686-w64-mingw32-g++"
set_toolset "mm" "i686-w64-mingw32-gcc"
set_toolset "mxx" "i686-w64-mingw32-gcc" "i686-w64-mingw32-g++"
set_toolset "ld" "i686-w64-mingw32-g++" "i686-w64-mingw32-gcc"
set_toolset "sh" "i686-w64-mingw32-g++" "i686-w64-mingw32-gcc"
set_toolset "ar" "i686-w64-mingw32-ar" "ar"
toolchain_end
# aarch64 toolchain (aarch64)
toolchain "aarch64_linux_gnu"
set_toolset "as" "aarch64-linux-gnu-gcc"
set_toolset "cc" "aarch64-linux-gnu-gcc"
set_toolset "cxx" "aarch64-linux-gnu-gcc" "aarch64-linux-gnu-g++"
set_toolset "mm" "aarch64-linux-gnu-gcc"
set_toolset "mxx" "aarch64-linux-gnu-gcc" "aarch64-linux-gnu-g++"
set_toolset "ld" "aarch64-linux-gnu-g++" "aarch64-linux-gnu-gcc"
set_toolset "sh" "aarch64-linux-gnu-g++" "aarch64-linux-gnu-gcc"
set_toolset "ar" "aarch64-linux-gnu-ar" "ar"
toolchain_end
# emcc toolchain (wasm32)
toolchain "emcc"
set_toolset "as" "emcc"
set_toolset "cc" "emcc"
set_toolset "cxx" "emcc" "em++"
set_toolset "mm" "emcc"
set_toolset "mxx" "emcc" "em++"
set_toolset "ld" "em++" "emcc"
set_toolset "sh" "em++" "emcc"
set_toolset "ar" "emar" "ar"
toolchain_end
# check platform
_check_platform() {
if test "x${_target_plat}" = "x"; then
_target_plat=${_target_plat_default}
fi
if test "x${_target_arch}" = "x"; then
_target_arch=${_target_arch_default}
fi
if test "x${_target_mode}" = "x"; then
_target_mode=${_target_mode_default}
fi
if test "x${_target_kind}" = "x"; then
_target_kind=${_target_kind_default}
fi
echo "checking for platform ... ${_target_plat}"
echo "checking for architecture ... ${_target_arch}"
}
# get toolchain compile command for gcc/clang
_toolchain_compcmd_for_gcc_clang() {
local program="${1}"
local objectfile="${2}"
local sourcefile="${3}"
local flags="${4}"
_ret="${program} -c ${flags} -o ${objectfile} ${sourcefile}"
}
# get toolchain link command for gcc/clang
_toolchain_linkcmd_for_gcc_clang() {
local toolkind="${1}"
local program="${2}"
local binaryfile="${3}"
local objectfiles="${4}"
local flags="${5}"
if test_eq "${toolkind}" "sh"; then
flags="-shared -fPIC ${flags}"
fi
_ret="${program} -o ${binaryfile} ${objectfiles} ${flags}"
}
# get toolchain link command for ar
_toolchain_linkcmd_for_ar() {
local toolkind="${1}"
local program="${2}"
local binaryfile="${3}"
local objectfiles="${4}"
local flags="${5}"
_ret="${program} ${flags} ${binaryfile} ${objectfiles}"
}
# get toolchain compile command
_toolchain_compcmd() {
local sourcekind="${1}"
local objectfile="${2}"
local sourcefile="${3}"
local flags="${4}"
_get_toolchain_toolset "${_target_toolchain}" "${sourcekind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
local compcmd=""
case "${toolname}" in
gcc) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
gxx) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
clang) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
clangxx) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
emcc) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
emxx) _toolchain_compcmd_for_gcc_clang "${program}" "${objectfile}" "${sourcefile}" "${flags}"; compcmd="${_ret}";;
*) raise "unknown toolname(${toolname})!" ;;
esac
_ret="${compcmd}"
}
# get toolchain link command
_toolchain_linkcmd() {
local toolkind="${1}"
local binaryfile="${2}"
local objectfiles="${3}"
local flags="${4}"
_get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
case "${toolname}" in
gcc) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
gxx) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
clang) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
clangxx) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
emcc) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
emxx) _toolchain_linkcmd_for_gcc_clang "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
ar) _toolchain_linkcmd_for_ar "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
emar) _toolchain_linkcmd_for_ar "${toolkind}" "${program}" "${binaryfile}" "${objectfiles}" "${flags}"; linkcmd="${_ret}";;
*) raise "unknown toolname(${toolname})!" ;;
esac
_ret="${linkcmd}"
}
# try make
_toolchain_try_make() {
local program="${1}"
if _os_runv "${program}" "--version"; then
return 0
fi
return 1
}
# try ninja
_toolchain_try_ninja() {
local program="${1}"
if _os_runv "${program}" "--version"; then
return 0
fi
return 1
}
# try gcc
_toolchain_try_gcc() {
if test "x${_toolchain_try_gcc_result}" = "xok"; then
return 0
elif test "x${_toolchain_try_gcc_result}" = "xno"; then
return 1
fi
local kind="${1}"
local program="${2}"
if _os_runv "${program}" "--version"; then
_toolchain_try_gcc_result="ok"
return 0
fi
_toolchain_try_gcc_result="no"
return 1
}
# try g++
_toolchain_try_gxx() {
if test "x${_toolchain_try_gxx_result}" = "xok"; then
return 0
elif test "x${_toolchain_try_gxx_result}" = "xno"; then
return 1
fi
local kind="${1}"
local program="${2}"
if _os_runv "${program}" "--version"; then
_toolchain_try_gxx_result="ok"
return 0
fi
_toolchain_try_gxx_result="no"
return 1
}
# try clang
_toolchain_try_clang() {
if test "x${_toolchain_try_clang_result}" = "xok"; then
return 0
elif test "x${_toolchain_try_clang_result}" = "xno"; then
return 1
fi
local kind="${1}"
local program="${2}"
if _os_runv "${program}" "--version"; then
_toolchain_try_clang_result="ok"
return 0
fi
_toolchain_try_clang_result="no"
return 1
}
# try clang++
_toolchain_try_clangxx() {
if test "x${_toolchain_try_clangxx_result}" = "xok"; then
return 0
elif test "x${_toolchain_try_clangxx_result}" = "xno"; then
return 1
fi
local kind="${1}"
local program="${2}"
if _os_runv "${program}" "--version"; then
_toolchain_try_clangxx_result="ok"
return 0
fi
_toolchain_try_clangxx_result="no"
return 1
}
# try ar
_toolchain_try_ar() {
local kind="${1}"
local program="${2}"
# generate the source file
_os_tmpfile
local tmpfile="${_ret}"
local objectfile="${tmpfile}.o"
local libraryfile="${tmpfile}.a"
echo "" > "${objectfile}"
# try linking it
local ok=false
if _os_runv "${program}" "-cr" "${libraryfile}" "${objectfile}"; then
ok=true
fi
# remove files
_os_tryrm "${objectfile}"
_os_tryrm "${libraryfile}"
if ${ok}; then
return 0
fi
return 1
}
# try program
_toolchain_try_program() {
local toolchain="${1}"
local kind="${2}"
local program="${3}"
local ok=false
path_toolname "${program}"; local toolname="${_ret}"
case "${toolname}" in
gcc) _toolchain_try_gcc "${kind}" "${program}" && ok=true;;
gxx) _toolchain_try_gxx "${kind}" "${program}" && ok=true;;
clang) _toolchain_try_clang "${kind}" "${program}" && ok=true;;
clangxx) _toolchain_try_clangxx "${kind}" "${program}" && ok=true;;
emcc) _toolchain_try_clang "${kind}" "${program}" && ok=true;;
emxx) _toolchain_try_clangxx "${kind}" "${program}" && ok=true;;
ar) _toolchain_try_ar "${kind}" "${program}" && ok=true;;
emar) _toolchain_try_ar "${kind}" "${program}" && ok=true;;
*) raise "unknown toolname(${toolname})!" ;;
esac
if ${ok}; then
vprint "checking for ${program} ... ok"
return 0
fi
vprint "checking for ${program} ... no"
return 1
}
# try toolset
_toolchain_try_toolset() {
local toolchain=${1}
local kind=${2}
local description=${3}
local indices="0 1 2 3 4 5"
for idx in ${indices}; do
local key="${kind}"
if test_nq "${idx}" "0"; then
key="${key}_${idx}"
fi
_get_toolchain_toolset "${toolchain}" "${key}"; local program="${_ret}"
if test_nz "${program}"; then
if _toolchain_try_program "${toolchain}" "${kind}" "${program}"; then
_set_toolchain_toolset "${toolchain}" "${kind}" "${program}"
echo "checking for the ${description} (${kind}) ... ${program}"
return 0
fi
fi
done
return 1
}
# try toolchain
_toolchain_try() {
local toolchain=${1}
vprint "checking for $toolchain toolchain ..."
if _toolchain_try_toolset "${toolchain}" "cc" "c compiler" &&
_toolchain_try_toolset "${toolchain}" "cxx" "c++ compiler" &&
_toolchain_try_toolset "${toolchain}" "as" "assembler" &&
_toolchain_try_toolset "${toolchain}" "mm" "objc compiler" &&
_toolchain_try_toolset "${toolchain}" "mxx" "objc++ compiler" &&
_toolchain_try_toolset "${toolchain}" "ld" "linker" &&
_toolchain_try_toolset "${toolchain}" "ar" "static library archiver" &&
_toolchain_try_toolset "${toolchain}" "sh" "shared library linker"; then
return 0
fi
return 1
}
# detect make
_toolchain_detect_make() {
if test "x${_make_program}" = "x"; then
_make_program=${_make_program_default}
fi
if _toolchain_try_make "${_make_program}"; then
echo "checking for make ... ok"
else
echo "checking for make ... no"
raise "make not found!"
fi
}
# detect ninja
_toolchain_detect_ninja() {
if test "x${_ninja_program}" = "x"; then
_ninja_program=${_ninja_program_default}
fi
if _toolchain_try_ninja "${_ninja_program}"; then
echo "checking for ninja ... ok"
else
echo "checking for ninja ... no"
raise "ninja not found!"
fi
}
# detect build backend
_toolchain_detect_backend() {
if test "x${_project_generator}" = "xgmake"; then
_toolchain_detect_make
elif test "x${_project_generator}" = "xninja"; then
_toolchain_detect_ninja
fi
}
# detect toolchain
_toolchain_detect() {
# detect build backend
_toolchain_detect_backend
# detect toolchains
local toolchains="${1}"
if test "x${toolchains}" = "x"; then
if is_plat "macosx"; then
toolchains="envs clang gcc"
elif is_plat "mingw"; then
if is_arch "i386"; then
toolchains="i686_w64_mingw32"
else
toolchains="x86_64_w64_mingw32"
fi
elif is_plat "wasm"; then
toolchains="emcc"
elif is_plat "linux" && ! is_arch "${os_arch}"; then
toolchains="envs"
if is_arch "arm64"; then
toolchains="${toolchains} aarch64_linux_gnu"
fi
else
toolchains="envs gcc clang"
fi
fi
for toolchain in ${toolchains}; do
if _toolchain_try "$toolchain"; then
_target_toolchain=${toolchain}
break
fi
done
}
# check toolchain
_check_toolchain() {
local toolchain=${_target_toolchain}
_target_toolchain=""
_toolchain_detect ${toolchain}
if test "x${_target_toolchain}" != "x"; then
echo "checking for toolchain ... ${_target_toolchain}"
else
echo "checking for toolchain ... no"
raise "toolchain not found!"
fi
}
# get function code
#
# sigsetjmp
# sigsetjmp((void*)0, 0)
#
_get_funccode() {
local func="${1}"
local code=""
if string_contains "${func}" "("; then
code="${func}"
else
code="typedef void (*func_t)(); volatile func_t p${func} = (func_t)${func}; while (p${func}) {break;};"
fi
_ret="${code}"
}
# generate cxsnippets source code
_generate_cxsnippets_sourcecode() {
local funcs="${1}"
local includes="${2}"
local types="${3}"
local snippets="${4}"
local snippet_includes=""
for include in $includes; do
snippet_includes="${snippet_includes}#include \"${include}\"\n"
done
local snippet_types=""
for type in $types; do
string_replace "${type}" '[^a-zA-Z]' "_"; local typevar="${_ret}"
snippet_types="${snippet_types}typedef ${type} __type_${typevar};\n"
done
local snippet_funcs=""
for func in $funcs; do
_get_funccode "${func}"; func="${_ret}"
snippet_funcs="${snippet_funcs}${func}\n "
done
local snippets_code=""
if test_nz "${snippet_includes}"; then
snippets_code="${snippets_code}${snippet_includes}\n"
fi
if test_nz "${snippet_types}"; then
snippets_code="${snippets_code}${snippet_types}\n"
fi
if test_nz "${snippets}"; then
snippets_code="${snippets_code}${snippets}\n"
fi
_ret='
'"${snippets_code}"'int main(int argc, char** argv) {
'"${snippet_funcs}"'
return 0;
}'
}
# check cxsnippets
_check_cxsnippets() {
local name="${1}"
local kind="${2}"
_get_option_item "${name}" "${kind}funcs"; local funcs="${_ret}"
_get_option_item "${name}" "${kind}includes"; local includes="${_ret}"
_get_option_item "${name}" "${kind}types"; local types="${_ret}"
_get_option_item "${name}" "${kind}snippets"; local snippets="${_ret}"
if test_z "${funcs}" && test_z "${includes}" &&
test_z "${types}" && test_z "${snippets}"; then
return 0
fi
# get c/c++ extension
local extension=".c"
local sourcekind="cc"
if test_eq "${kind}" "cxx"; then
extension=".cpp"
sourcekind="cxx"
fi
# generate source code
_generate_cxsnippets_sourcecode "${funcs}" "${includes}" "${types}" "${snippets}"; local sourcecode="${_ret}"
dprint "${sourcecode}"
# generate the source file
_os_tmpfile
local tmpfile="${_ret}"
local sourcefile="${tmpfile}${extension}"
local objectfile="${tmpfile}.o"
local binaryfile="${tmpfile}.bin"
print "${sourcecode}" > "${sourcefile}"
# try compiling it
local ok=false
if ! ${ok}; then
local compflags=""
_get_toolchain_toolset "${_target_toolchain}" "${sourcekind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
local itemnames="languages warnings optimizes defines undefines includedirs"
for itemname in ${itemnames}; do
_get_option_abstract_flags "${name}" "${sourcekind}" "${toolname}" "${itemname}"; local flags="${_ret}"
if test_nz "${flags}"; then
_split_flags "${flags}"; flags="${_ret}"
compflags="${compflags} ${flags}"
fi
done
local flagnames="cxflags"
if test_eq "${sourcekind}" "cxx"; then
flagnames="${flagnames} cxxflags"
else
flagnames="${flagnames} cflags"
fi
for flagname in $flagnames; do
_get_option_item "${name}" "${flagname}"; local flags="${_ret}"
if test_nz "${flags}"; then
compflags="${compflags} ${flags}"
fi
done
if test_eq "${sourcekind}" "cxx"; then
if test_nz "${CXXFLAGS}"; then
compflags="${compflags} ${CXXFLAGS}"
fi
else
if test_nz "${CFLAGS}"; then
compflags="${compflags} ${CFLAGS}"
fi
fi
if test_nz "${CPPFLAGS}"; then
compflags="${compflags} ${CPPFLAGS}"
fi
_toolchain_compcmd "${sourcekind}" "${objectfile}" "${sourcefile}" "${compflags}"; local compcmd="${_ret}"
if ${xmake_sh_diagnosis}; then
print "> ${compcmd}"
fi
if _os_runv ${compcmd}; then
ok=true
fi
fi
# try linking it
_get_option_item "${name}" "links"; local links="${_ret}"
_get_option_item "${name}" "syslinks"; local syslinks="${_ret}"
_get_option_item "${name}" "ldflags"; local ldflags="${_ret}"
if test_nz "${syslinks}"; then
links="${links} ${syslinks}"
fi
if ${ok} && (test_nz "${links}" || test_nz "${ldflags}"); then
local toolkind="ld"
_get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
local itemnames="linkdirs links syslinks"
local linkflags=""
for itemname in ${itemnames}; do
_get_option_abstract_flags "${name}" "${toolkind}" "${toolname}" "${itemname}"; local flags="${_ret}"
if test_nz "${flags}"; then
_split_flags "${flags}"; flags="${_ret}"
linkflags="${linkflags} ${flags}"
fi
done
_get_option_item "${name}" "ldflags"; local flags="${_ret}"
if test_nz "${flags}"; then
linkflags="${linkflags} ${flags}"
fi
if test_nz "${LDFLAGS}"; then
linkflags="${linkflags} ${LDFLAGS}"
fi
_toolchain_linkcmd "${toolkind}" "${binaryfile}" "${objectfile}" "${linkflags}"; local linkcmd="${_ret}"
if ${xmake_sh_diagnosis}; then
print "> ${linkcmd}"
fi
if _os_runv ${linkcmd}; then
ok=true
else
ok=false
fi
fi
# trace
if ${xmake_sh_verbose} || ${xmake_sh_diagnosis}; then
if test_nz "${includes}"; then
print "> checking for ${kind} includes(${includes})"
fi
if test_nz "${types}"; then
print "> checking for ${kind} types(${types})"
fi
if test_nz "${funcs}"; then
print "> checking for ${kind} funcs(${funcs})"
fi
if test_nz "${links}"; then
print "> checking for ${kind} links(${links})"
fi
fi
# remove files
_os_tryrm "${sourcefile}"
_os_tryrm "${objectfile}"
_os_tryrm "${binaryfile}"
if ${ok}; then
return 0
fi
return 1
}
# check csnippets
_check_csnippets() {
local name="${1}"
if _check_cxsnippets "${name}" "c"; then
return 0
fi
return 1
}
# check cxxsnippets
_check_cxxsnippets() {
local name="${1}"
if _check_cxsnippets "${name}" "cxx"; then
return 0
fi
return 1
}
# check option
_check_option() {
local name="${1}"
_get_option_value "${name}"; local value="${_ret}"
_get_option_item "${name}" "default"; local default="${_ret}"
if test_nz "${value}"; then
if _is_enabled "${value}"; then
return 0
else
return 1
fi
elif test_nz "${default}"; then
if _is_enabled "${default}"; then
return 0
else
return 1
fi
else
_get_option_item "${name}" "before_check"; local before_check="${_ret}"
if test_nz "${before_check}"; then
eval ${before_check}
fi
if _check_csnippets "${name}" && _check_cxxsnippets "${name}"; then
return 0
fi
fi
return 1
}
# check options
_check_options() {
_get_options_for_checking; local options="${_ret}"
for name in $options; do
if _check_option "$name"; then
echo "checking for ${name} .. ok"
_set_option_value "${name}" true
else
echo "checking for ${name} .. no"
_set_option_value "${name}" false
fi
done
}
# check all
_check_all() {
_check_platform
_check_toolchain
_check_options
}
_check_all
#-----------------------------------------------------------------------------
# init builtin variables, e.g. add_headerfiles "${buildir}/config.h"
#
projectdir="${xmake_sh_projectdir}"
if path_is_absolute "${xmake_sh_buildir}"; then
buildir="${xmake_sh_buildir}"
else
buildir="${xmake_sh_projectdir}/${xmake_sh_buildir}"
fi
plat="${_target_plat}"
arch="${_target_arch}"
mode="${_target_mode}"
kind="${_target_kind}"
#-----------------------------------------------------------------------------
# load project targets
#
# load targets
_load_targets() {
echo "analyzing project configuration .."
_loading_options=false
_loading_toolchains=false
_loading_targets=true
_xmake_sh_option_current=""
_xmake_sh_target_current=""
_xmake_sh_toolchain_current=""
local file=${xmake_sh_projectdir}/xmake.sh
if test -f "${file}"; then
includes "${file}"
else
# include all xmake.sh files in next sub-directories
_os_find "${xmake_sh_projectdir}" "xmake.sh" 2; local files="${_ret}"
for file in ${files}; do
includes "${file}"
done
fi
}
_load_targets
# get toolset kinds for all targets
# e.g. cc cxx as mm mxx ld sh ar
_get_targets_toolkinds() {
if test_z "${_targets_toolkinds_dedup}"; then
_dedup "${_targets_toolkinds}"; _targets_toolkinds_dedup="${_ret}"
fi
_ret="${_targets_toolkinds_dedup}"
}
#-----------------------------------------------------------------------------
# generate configfiles
#
# vprint config variable in `${name}`
_vprint_configvar_value() {
local name="${1}"
local value="${2}"
vprint " > replace ${name} -> ${value}"
}
# vprint config variable in `${define name}`
_vprint_configvar_define() {
local name="${1}"
local value="${2}"
if test_z "${value}"; then
vprint " > replace ${name} -> /* #undef ${name} */"
elif test_eq "${value}" "1" || test_eq "${value}" "true"; then
vprint " > replace ${name} -> #define ${name} 1"
elif test_eq "${value}" "0" || test_eq "${value}" "false"; then
vprint " > replace ${name} -> /*#define ${name} 0*/"
else
vprint " > replace ${name} -> #define ${name} ${value}"
fi
}
# replace config variable in `${define name}`
_replace_configvar_define() {
local name="${1}"
local value="${2}"
if test_z "${value}"; then
_ret="s/\${define ${name}}/\/*#undef ${name}*\//g"
elif test_eq "${value}" "1" || test_eq "${value}" "true"; then
_ret="s/\${define ${name}}/#define ${name} 1/g"
elif test_eq "${value}" "0" || test_eq "${value}" "false"; then
_ret="s/\${define ${name}}/\/*#define ${name} 0*\//g"
else
_ret="s/\${define ${name}}/#define ${name} ${value}/g"
fi
}
# replace config variable in `${name}`
_replace_configvar_value() {
local name="${1}"
local value="${2}"
_ret="s/\${${name}}/${value}/g"
}
# generate configfile for the given target
_generate_configfile() {
local target="${1}"
local configfile_in="${2}"
_get_target_item "${target}" "configdir"; local configdir="${_ret}"
if test_z "${configdir}"; then
path_directory configfile_in; configdir="${_ret}"
fi
if ! test -d "${configdir}"; then
mkdir -p "${configdir}"
fi
path_basename "${configfile_in}"; local filename="${_ret}"
local configfile="${configdir}/${filename}"
echo "generating ${configfile} .."
# replace builtin variables
local patterns=""
local target_os=""
if is_plat "mingw"; then
target_os="windows"
else
target_os="${_target_plat}"
fi
string_toupper ${target_os}; target_os="${_ret}"
_vprint_configvar_value "OS" "${target_os}"
_replace_configvar_value "OS" "${target_os}"; patterns="${_ret};${patterns}"
# replace version
_get_target_item "${target}" "version"; local version="${_ret}"
_get_target_item "${target}" "version_build"; local version_build="${_ret}"
string_split "${version}" "."
local version_major="${_ret}"
local version_minor="${_ret2}"
local version_alter="${_ret3}"
if test_nz "${version}"; then
_vprint_configvar_value "VERSION" "${version}"
_replace_configvar_value "VERSION" "${version}"; patterns="${_ret};${patterns}"
fi
if test_nz "${version_major}"; then
_vprint_configvar_value "VERSION_MAJOR" "${version_major}"
_replace_configvar_value "VERSION_MAJOR" "${version_major}"; patterns="${_ret};${patterns}"
fi
if test_nz "${version_minor}"; then
_vprint_configvar_value "VERSION_MINOR" "${version_minor}"
_replace_configvar_value "VERSION_MINOR" "${version_minor}"; patterns="${_ret};${patterns}"
fi
if test_nz "${version_alter}"; then
_vprint_configvar_value "VERSION_ALTER" "${version_alter}"
_replace_configvar_value "VERSION_ALTER" "${version_alter}"; patterns="${_ret};${patterns}"
fi
if test_nz "${version_build}"; then
_os_date "${version_build}"; version_build="${_ret}"
_vprint_configvar_value "VERSION_BUILD" "${version_build}"
_replace_configvar_value "VERSION_BUILD" "${version_build}"; patterns="${_ret};${patterns}"
fi
# replace git variables
local content=""
content=$(cat "${configfile_in}")
if string_contains "${content}" "GIT_"; then
_os_iorunv "git" "describe" "--tags"; local git_tag="${_ret}"
_vprint_configvar_value "GIT_TAG" "${git_tag}"
_replace_configvar_value "GIT_TAG" "${git_tag}"; patterns="${_ret};${patterns}"
_os_iorunv "git" "describe" "--tags" "--long"; local git_tag_long="${_ret}"
_vprint_configvar_value "GIT_TAG_LONG" "${git_tag_long}"
_replace_configvar_value "GIT_TAG_LONG" "${git_tag_long}"; patterns="${_ret};${patterns}"
_os_iorunv "git" "rev-parse" "--abbrev-ref" "HEAD"; local git_branch="${_ret}"
_vprint_configvar_value "GIT_BRANCH" "${git_branch}"
_replace_configvar_value "GIT_BRANCH" "${git_branch}"; patterns="${_ret};${patterns}"
_os_iorunv "git" "rev-parse" "--short" "HEAD"; local git_commit="${_ret}"
_vprint_configvar_value "GIT_COMMIT" "${git_commit}"
_replace_configvar_value "GIT_COMMIT" "${git_commit}"; patterns="${_ret};${patterns}"
_os_iorunv "git" "rev-parse" "HEAD"; local git_commit_long="${_ret}"
_vprint_configvar_value "GIT_COMMIT_LONG" "${git_commit_long}"
_replace_configvar_value "GIT_COMMIT_LONG" "${git_commit_long}"; patterns="${_ret};${patterns}"
_os_iorunv "log" "-1" "--date=format:%Y%m%d%H%M%S" "--format=%ad"; local git_commit_date="${_ret}"
_vprint_configvar_value "GIT_COMMIT_DATE" "${git_commit_date}"
_replace_configvar_value "GIT_COMMIT_DATE" "${git_commit_date}"; patterns="${_ret};${patterns}"
fi
# replace configvars in target
local count=0
local configfile_dst="${configfile}"
_os_tmpfile; local tmpfile="${_ret}"
cp "${configfile_in}" "${tmpfile}"
_get_target_item "${target}" "configvars"; local configvars="${_ret}"
for name in ${configvars}; do
_get_target_item "${target}" "configvar_${name}"; local value="${_ret}"
_vprint_configvar_define "${name}" "${value}"
_vprint_configvar_value "${name}" "${value}"
_replace_configvar_define "${name}" "${value}"; patterns="${_ret};${patterns}"
_replace_configvar_value "${name}" "${value}"; patterns="${_ret};${patterns}"
count=$((count + 1))
# do replace
if test_eq "$count" "10"; then
_io_replace_file "${tmpfile}" "${configfile}" "${patterns}"
local swapfile="${tmpfile}"
tmpfile="${configfile}"
configfile="${swapfile}"
patterns=""
count=0
fi
done
# do replace (left)
if test_nz "${patterns}"; then
_io_replace_file "${tmpfile}" "${configfile}" "${patterns}"
local swapfile="${tmpfile}"
tmpfile="${configfile}"
configfile="${swapfile}"
patterns=""
count=0
fi
# replace fallback
patterns='s/${define \(.*\)}/\/*#undef \1*\//g;'
_io_replace_file "${tmpfile}" "${configfile}" "${patterns}"
if test_nq "${configfile}" "${configfile_dst}"; then
cp "${configfile}" "${configfile_dst}"
fi
echo "${configfile_dst} is generated!"
}
# generate configfiles
_generate_configfiles() {
for target in ${_xmake_sh_targets}; do
_get_target_item "${target}" "configfiles"; local configfiles="${_ret}"
for configfile in ${configfiles}; do
_generate_configfile "${target}" "${configfile}"
done
done
}
_generate_configfiles
#-----------------------------------------------------------------------------
# generate gmake file
#
_gmake_begin() {
echo "generating makefile .."
}
_gmake_add_header() {
echo "# this is the build file for this project
# it is autogenerated by the xmake.sh build system.
# do not edit by hand.
" > "${xmake_sh_makefile}"
}
_gmake_add_switches() {
echo "ifneq (\$(VERBOSE),1)" >> "${xmake_sh_makefile}"
echo "VV=@" >> "${xmake_sh_makefile}"
echo "endif" >> "${xmake_sh_makefile}"
echo "" >> "${xmake_sh_makefile}"
echo "ifeq (\$(PREFIX),)" >> "${xmake_sh_makefile}"
echo "PREFIX=${_install_prefix_default}" >> "${xmake_sh_makefile}"
echo "endif" >> "${xmake_sh_makefile}"
echo "" >> "${xmake_sh_makefile}"
echo "INSTALLDIR:=\$(DESTDIR)" >> "${xmake_sh_makefile}"
echo "ifneq (\$(PREFIX),)" >> "${xmake_sh_makefile}"
echo "ifneq (\$(INSTALLDIR),)" >> "${xmake_sh_makefile}"
echo "PREFIX_:=\$(patsubst /%,%,\$(PREFIX))" >> "${xmake_sh_makefile}"
echo "INSTALLDIR:=\$(INSTALLDIR)/\$(PREFIX_)" >> "${xmake_sh_makefile}"
echo "else" >> "${xmake_sh_makefile}"
echo "INSTALLDIR:=\$(PREFIX)" >> "${xmake_sh_makefile}"
echo "endif" >> "${xmake_sh_makefile}"
echo "endif" >> "${xmake_sh_makefile}"
echo "" >> "${xmake_sh_makefile}"
}
_gmake_add_flags() {
_get_targets_toolkinds; local kinds="${_ret}"
for target in ${_xmake_sh_targets}; do
for kind in ${kinds}; do
_get_target_flags "${target}" "${kind}"; local flags="${_ret}"
_get_flagname "${kind}"; local flagname="${_ret}"
local key="${target}_${flagname}"
echo "${key}=${flags}" >> "${xmake_sh_makefile}"
done
echo "" >> "${xmake_sh_makefile}"
done
}
_gmake_add_toolchains() {
_get_targets_toolkinds; local kinds="${_ret}"
for kind in ${kinds}; do
_get_toolchain_toolset "${_target_toolchain}" "${kind}"; local program="${_ret}"
local key="${kind}"
echo "${key}=${program}" >> "${xmake_sh_makefile}"
done
echo "" >> "${xmake_sh_makefile}"
}
_gmake_add_build_object_for_gcc_clang() {
local kind="${1}"
local sourcefile="${2}"
local objectfile="${3}"
local flagname="${4}"
path_directory "${objectfile}"; local objectdir="${_ret}"
print "\t@mkdir -p ${objectdir}" >> "${xmake_sh_makefile}"
print "\t\$(VV)\$(${kind}) -c \$(${flagname}) -o ${objectfile} ${sourcefile}" >> "${xmake_sh_makefile}"
}
_gmake_add_build_object() {
local target=${1}
local sourcefile="${2}"
local objectfile="${3}"
path_sourcekind "${sourcefile}"; local sourcekind="${_ret}"
_get_toolchain_toolset "${_target_toolchain}" "${sourcekind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
_get_flagname "${sourcekind}"; local flagname="${_ret}"
flagname="${target}_${flagname}"
echo "${objectfile}: ${sourcefile}" >> "${xmake_sh_makefile}"
print "\t@echo compiling.${_target_mode} ${sourcefile}" >> "${xmake_sh_makefile}"
case "${toolname}" in
gcc) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
gxx) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
clang) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
clangxx) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
emcc) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
emxx) _gmake_add_build_object_for_gcc_clang "${sourcekind}" "${sourcefile}" "${objectfile}" "${flagname}";;
*) raise "unknown toolname(${toolname})!" ;;
esac
echo "" >> "${xmake_sh_makefile}"
}
_gmake_add_build_objects() {
local target=${1}
_get_target_sourcefiles "${target}"; local sourcefiles="${_ret}"
for sourcefile in ${sourcefiles}; do
_get_target_objectfile "${target}" "${sourcefile}"; local objectfile="${_ret}"
_gmake_add_build_object "${target}" "${sourcefile}" "${objectfile}"
done
}
_gmake_add_build_target_for_gcc_clang() {
local kind="${1}"
local targetfile="${2}"
local objectfiles="${3}"
local flagname="${4}"
path_directory "${targetfile}"; local targetdir="${_ret}"
print "\t@mkdir -p ${targetdir}" >> "${xmake_sh_makefile}"
print "\t\$(VV)\$(${kind}) -o ${targetfile} ${objectfiles} \$(${flagname})" >> "${xmake_sh_makefile}"
}
_gmake_add_build_target_for_ar() {
local kind="${1}"
local targetfile="${2}"
local objectfiles="${3}"
local flagname="${4}"
path_directory "${targetfile}"; local targetdir="${_ret}"
print "\t@mkdir -p ${targetdir}" >> "${xmake_sh_makefile}"
print "\t\$(VV)\$(${kind}) \$(${flagname}) ${flags} ${targetfile} ${objectfiles}" >> "${xmake_sh_makefile}"
}
_gmake_add_build_target() {
local target=${1}
_get_targetdir "${target}"; local targetdir="${_ret}"
_get_target_file "${target}"; local targetfile="${_ret}"
_get_target_item "${target}" "deps"; local deps="${_ret}"
_get_target_objectfiles "${target}"; local objectfiles="${_ret}"
# get linker
_get_target_item "${target}" "kind"; local targetkind="${_ret}"
local toolkind=""
case "${targetkind}" in
binary) toolkind="ld";;
static) toolkind="ar";;
shared) toolkind="sh";;
*) raise "unknown targetkind(${targetkind})!" ;;
esac
_get_toolchain_toolset "${_target_toolchain}" "${toolkind}"; local program="${_ret}"
path_toolname "${program}"; local toolname="${_ret}"
# get linker flags
_get_flagname "${toolkind}"; local flagname="${_ret}"
flagname="${target}_${flagname}"
# get depfiles
local dep=""
local depfiles=""
for dep in ${deps}; do
_get_target_file "${dep}"; local depfile="${_ret}"
if test_nz "${depfiles}"; then
depfiles="${depfiles} ${depfile}"
else
depfiles="${depfile}"
fi
done
# link target
echo "${target}: ${targetfile}" >> "${xmake_sh_makefile}"
echo "${targetfile}: ${depfiles}${objectfiles}" >> "${xmake_sh_makefile}"
print "\t@echo linking.${_target_mode} ${targetfile}" >> "${xmake_sh_makefile}"
case "${toolname}" in
gcc) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
gxx) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
clang) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
clangxx) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
emcc) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
emxx) _gmake_add_build_target_for_gcc_clang "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
ar) _gmake_add_build_target_for_ar "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
emar) _gmake_add_build_target_for_ar "${toolkind}" "${targetfile}" "${objectfiles}" "${flagname}";;
*) raise "unknown toolname(${toolname})!" ;;
esac
echo "" >> "${xmake_sh_makefile}"
# build objects
_gmake_add_build_objects "${target}"
}
_gmake_add_build_targets() {
local target=""
local defaults=""
for target in ${_xmake_sh_targets}; do
if _is_target_default "${target}"; then
defaults="${defaults} ${target}"
fi
done
echo "default:${defaults}" >> "${xmake_sh_makefile}"
echo "all:${_xmake_sh_targets}" >> "${xmake_sh_makefile}"
echo ".PHONY: default all" >> "${xmake_sh_makefile}"
echo "" >> "${xmake_sh_makefile}"
for target in ${_xmake_sh_targets}; do
_gmake_add_build_target "${target}"
done
}
_gmake_add_build() {
_gmake_add_build_targets
}
_gmake_add_run_target() {
local target=${1}
_get_target_file "${target}"; local targetfile="${_ret}"
print "\t@${targetfile}" >> "${xmake_sh_makefile}"
}
_gmake_add_run_targets() {
local target=""
local targets=""
for target in ${_xmake_sh_targets}; do
_get_target_item "${target}" "kind"; local kind="${_ret}"
if test "x${kind}" = "xbinary"; then
if _is_target_default "${target}"; then
targets="${targets} ${target}"
fi
fi
done
echo "run:${targets}" >> "${xmake_sh_makefile}"
for target in ${targets}; do
_gmake_add_run_target "${target}"
done
echo "" >> "${xmake_sh_makefile}"
}
_gmake_add_run() {
_gmake_add_run_targets
}
_gmake_add_clean_target() {
local target=${1}
local objectfile=""
_get_target_file "${target}"; local targetfile="${_ret}"
_get_target_objectfiles "${target}"; local objectfiles="${_ret}"
print "\t@rm ${targetfile}" >> "${xmake_sh_makefile}"
for objectfile in ${objectfiles}; do
print "\t@rm ${objectfile}" >> "${xmake_sh_makefile}"
done
}
_gmake_add_clean_targets() {
local target=""
local targets=""
for target in ${_xmake_sh_targets}; do
if _is_target_default "${target}"; then
targets="${targets} ${target}"
fi
done
echo "clean:${targets}" >> "${xmake_sh_makefile}"
for target in ${targets}; do
_gmake_add_clean_target "${target}"
done
echo "" >> "${xmake_sh_makefile}"
}
_gmake_add_clean() {
_gmake_add_clean_targets
}
_gmake_add_install_target() {
local target=${1}
_get_target_file "${target}"; local targetfile="${_ret}"
path_filename "${targetfile}"; local filename="${_ret}"
_get_target_item "${target}" "installdir"; local installdir="${_ret}"
if test_z "${installdir}"; then
installdir="\$(INSTALLDIR)"
fi
# install target file
_get_target_item "${target}" "kind"; local targetkind="${_ret}"
if test_eq "${targetkind}" "binary"; then
string_replace "${_install_bindir_default}" "\${prefix}" "${installdir}"; _install_bindir_default="${_ret}"
print "\t@echo installing ${targetfile} to ${_install_bindir_default}" >> "${xmake_sh_makefile}"
print "\t@mkdir -p ${_install_bindir_default}" >> "${xmake_sh_makefile}"
print "\t@cp -p ${targetfile} ${_install_bindir_default}/${filename}" >> "${xmake_sh_makefile}"
elif test_eq "${targetkind}" "static" || test_eq "${targetkind}" "shared"; then
string_replace "${_install_libdir_default}" "\${prefix}" "${installdir}"; _install_libdir_default="${_ret}"
print "\t@echo installing ${targetfile} to ${_install_libdir_default}" >> "${xmake_sh_makefile}"
print "\t@mkdir -p ${_install_libdir_default}" >> "${xmake_sh_makefile}"
print "\t@cp -p ${targetfile} ${_install_libdir_default}/${filename}" >> "${xmake_sh_makefile}"
fi
# install header files
_get_target_item "${target}" "headerfiles"; local headerfiles="${_ret}"
if test_nz "${headerfiles}"; then
string_replace "${_install_includedir_default}" "\${prefix}" "${installdir}"; _install_includedir_default="${_ret}"
local srcheaderfile=""
local includedir="${_install_includedir_default}"
for srcheaderfile in ${headerfiles}; do
string_split "${srcheaderfile}" ":"
local srcheaderfile="${_ret}"
local rootdir="${_ret2}"
local prefixdir="${_ret3}"
local filename="${_ret4}"
if test_z "${filename}"; then
path_filename "${srcheaderfile}"; filename="${_ret}"
fi
local dstheaderdir="${includedir}"
if test_nz "${prefixdir}"; then
dstheaderdir="${dstheaderdir}/${prefixdir}"
fi
local dstheaderfile="${dstheaderdir}/${filename}"
if test_nz "${rootdir}"; then
path_relative "${rootdir}" "${srcheaderfile}"; local subfile="${_ret}"
dstheaderfile="${dstheaderdir}/${subfile}"
fi
path_directory "${dstheaderfile}"; dstheaderdir="${_ret}"
print "\t@mkdir -p ${dstheaderdir}" >> "${xmake_sh_makefile}"
print "\t@cp -p ${srcheaderfile} ${dstheaderfile}" >> "${xmake_sh_makefile}"
done
fi
# install user files
_get_target_item "${target}" "installfiles"; local installfiles="${_ret}"
if test_nz "${installfiles}"; then
local srcinstallfile=""
for srcinstallfile in ${installfiles}; do
string_split "${srcinstallfile}" ":"
local srcinstallfile="${_ret}"
local rootdir="${_ret2}"
local prefixdir="${_ret3}"
local filename="${_ret4}"
if test_z "${filename}"; then
path_filename "${srcinstallfile}"; filename="${_ret}"
fi
local dstinstalldir="${installdir}"
if test_nz "${prefixdir}"; then
dstinstalldir="${dstinstalldir}/${prefixdir}"
fi
local dstinstallfile="${dstinstalldir}/${filename}"
if test_nz "${rootdir}"; then
path_relative "${rootdir}" "${srcinstallfile}"; local subfile="${_ret}"
dstinstallfile="${dstinstalldir}/${subfile}"
fi
path_directory "${dstinstallfile}"; dstinstalldir="${_ret}"
print "\t@mkdir -p ${dstinstalldir}" >> "${xmake_sh_makefile}"
print "\t@cp -p ${srcinstallfile} ${dstinstallfile}" >> "${xmake_sh_makefile}"
done
fi
}
_gmake_add_install_targets() {
local target=""
local targets=""
for target in ${_xmake_sh_targets}; do
if _is_target_default "${target}"; then
targets="${targets} ${target}"
fi
done
echo "install:${targets}" >> "${xmake_sh_makefile}"
for target in ${targets}; do
_gmake_add_install_target "${target}"
done
echo "" >> "${xmake_sh_makefile}"
}
_gmake_add_install() {
_gmake_add_install_targets
}
_gmake_done() {
echo "makefile is generated!"
if "${xmake_sh_diagnosis}"; then
cat "${xmake_sh_makefile}"
fi
}
# generate build file for gmake
_generate_for_gmake() {
_gmake_begin
_gmake_add_header
_gmake_add_switches
_gmake_add_toolchains
_gmake_add_flags
_gmake_add_build
_gmake_add_clean
_gmake_add_install
_gmake_add_run
_gmake_done
}
#-----------------------------------------------------------------------------
# generate ninja file
#
# generate build file for ninja
_generate_for_ninja() {
raise "Ninja generator has been not supported!"
}
#-----------------------------------------------------------------------------
# generate build file
#
_generate_build_file() {
if test_eq "${_project_generator}" "gmake"; then
_generate_for_gmake
elif test_eq "${_project_generator}" "ninja"; then
_generate_for_ninja
else
raise "unknown generator: ${_project_generator}"
fi
}
_generate_build_file
Lua
1
https://gitee.com/spkx/xmake.git
git@gitee.com:spkx/xmake.git
spkx
xmake
xmake
master

搜索帮助