2010-08-20 32 views

Trả lời

8

SCons không có một lệnh liên kết tượng trưng chuyên dụng, nhưng bạn có thể sử dụng os.symlink(src, dst) từ mô-đun os Python:

import os 
env = Environment() 
def SymLink(target, source, env): 
    os.symlink(os.path.abspath(str(source[0])), os.path.abspath(str(target[0]))) 
env.Command("file.out", "file.in", SymLink) 

này có thể không hoạt động chính xác trên Windows, tôi đã chỉ cố gắng nó trên Linux.

+0

Đối với một số lý do nó không hoạt động khi cố gắng để tạo ra một liên kết tượng trưng trong một subdir, như "env.Command (hương vị + '/ Tài nguyên', 'src/Tài nguyên', SymLink)" nơi mà hương vị là 'gỡ lỗi' hoặc 'phát hành'. – Septagram

+1

@Septagram xin vui lòng xem chỉnh sửa của tôi –

+0

Sẽ không hoạt động cho các tệp được cài đặt – RzR

1

Điều này tạo ra một người thợ xây để thực hiện các công việc:

mylib = env.SharedLibrary("foobar", SRCS) 

builder = Builder(action = "ln -s ${SOURCE.file} ${TARGET.file}", chdir = True) 

env.Append(BUILDERS = {"Symlink" : builder}) 

mylib_link = env.Symlink("_foobar.so", mylib) 

env.Default(mylib) 
env.Default(mylib_link) 

Một lần nữa, giải pháp này là dành cho Linux.

+1

Thật không may, nó không hoạt động tốt (ở tất cả) trên thư mục: "TypeError: Thư mục/home/septi/Dropbox/Code/StreetCleaner/src/Tài nguyên tìm thấy tệp dự kiến: " – Septagram

+0

@Septagram: Cách khắc phục sự cố thư mục? –

+0

@ Nordlöw, xin lỗi, nhưng đã lâu rồi và tôi không biết: (Vui lòng thử các câu trả lời khác và nhận xét nếu bạn tìm thấy điều gì đó. – Septagram

7

Dường như có chút tiến bộ trong mã lõi SCons để hỗ trợ liên kết tượng trưng và tôi không hài lòng bất kỳ giải pháp nào tôi tìm thấy trên web. Đây là một nhà xây dựng tiềm năng kết hợp các khía cạnh của cả hai câu trả lời của Nick và richq. Ngoài ra, nó sẽ bắt tên thay đổi (do phương pháp emitter) và là nền tảng bất khả tri như tôi có thể nhận được nó.

Tôi thích trình tạo này vì nó sẽ tạo liên kết liên quan đến thư mục mà chúng được cài đặt. Người ta có thể thêm một tùy chọn để buộc các liên kết được tuyệt đối tôi giả sử, nhưng tôi đã không cần thiết hoặc muốn được nêu ra.

Hiện tại, nếu hệ điều hành không hỗ trợ các liên kết tượng trưng, ​​tôi chỉ chuyển và không làm gì cả, nhưng có thể sử dụng os.copytree(), tuy nhiên phụ thuộc sẽ trở nên lộn xộn nếu nguồn là thư mục sao cho bộ phát sẽ cần làm một cái gì đó ưa thích. Tôi đang đưa ra bất kỳ đề xuất ở đây.

Người ta có thể đặt đoạn mã sau vào file site_scons/site_tools/symlink.py (với trống _ init _.py file ở các vị trí thích hợp). Sau đó thực hiện điều này trong file SConstruct:

SConstruct:

env = Environment() 
env.Tool('symlink') 
env.SymLink('link_name.txt', 'real_file.txt') 

symlink.py:

import os 
from os import path 

from SCons.Node import FS 
from SCons.Script import Action, Builder 

def generate(env): 
    ''' 
    SymLink(link_name,source) 
    env.SymLink(link_name,source) 

    Makes a symbolic link named "link_name" that points to the 
    real file or directory "source". The link produced is always 
    relative. 
    ''' 
    bldr = Builder(action = Action(symlink_builder,symlink_print), 
     target_factory = FS.File, 
     source_factory = FS.Entry, 
     single_target = True, 
     single_source = True, 
     emitter = symlink_emitter) 
    env.Append(BUILDERS = {'SymLink' : bldr}) 

def exists(env): 
    ''' 
    we could test if the OS supports symlinks here, or we could 
    use copytree as an alternative in the builder. 
    ''' 
    return True 

def symlink_print(target, source, env): 
    lnk = path.basename(target[0].abspath) 
    src = path.basename(source[0].abspath) 
    return 'Link: '+lnk+' points to '+src 

def symlink_emitter(target, source, env): 
    ''' 
    This emitter removes the link if the source file name has changed 
    since scons does not seem to catch this case. 
    ''' 
    lnk = target[0].abspath 
    src = source[0].abspath 
    lnkdir,lnkname = path.split(lnk) 
    srcrel = path.relpath(src,lnkdir) 

    if int(env.get('verbose',0)) > 3: 
     ldir = path.relpath(lnkdir,env.Dir('#').abspath) 
     if rellnkdir[:2] == '..': 
      ldir = path.abspath(ldir) 
     print ' symbolic link in directory: %s' % ldir 
     print '  %s -> %s' % (lnkname,srcrel) 

    try: 
     if path.exists(lnk): 
      if os.readlink(lnk) != srcrel: 
       os.remove(lnk) 
    except AttributeError: 
     # no symlink available, so we remove the whole tree? (or pass) 
     #os.rmtree(lnk) 
     print 'no os.symlink capability on this system?' 

    return (target, source) 

def symlink_builder(target, source, env): 
    lnk = target[0].abspath 
    src = source[0].abspath 
    lnkdir,lnkname = path.split(lnk) 
    srcrel = path.relpath(src,lnkdir) 

    if int(env.get('verbose',0)) > 4: 
     print 'target:', target 
     print 'source:', source 
     print 'lnk:', lnk 
     print 'src:', src 
     print 'lnkdir,lnkname:', lnkdir, lnkname 
     print 'srcrel:', srcrel 

    if int(env.get('verbose',0)) > 4: 
     print 'in directory: %s' % path.relpath(lnkdir,env.Dir('#').abspath) 
     print ' symlink: %s -> %s' % (lnkname,srcrel) 

    try: 
     os.symlink(srcrel,lnk) 
    except AttributeError: 
     # no symlink available, so we make a (deep) copy? (or pass) 
     #os.copytree(srcrel,lnk) 
     print 'no os.symlink capability on this system?' 

    return None 
+0

Bạn đã viết Tôi muốn giao diện tương tự như xây dựng 'Cài đặt' trong đó đối số đầu tiên là một thư mục. –

Các vấn đề liên quan